1. 程式人生 > 實用技巧 >《牛客演算法周練18》

《牛客演算法周練18》

B:救救企鵝

kmp標記一下位置即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef long double ld;
typedef pair<LL,int> pii;
const int N = 1e6+5;
const int M = 1e6+5;
const LL Mod = 998244353;
#define rg register
#define pi acos(-1)
#define INF 1e9
#define INM INT_MIN
#define
dbg(ax) cout << "now this num is " << ax << endl; inline int read() { int x = 0,f = 1;char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();} while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
return x*f; } int nxt[N],vis[N]; void pre_next(string t) { nxt[0] = -1; int len = t.size(),k = -1,i = 0; while(i < len) { if(k == -1 || nxt[i] == nxt[k]) nxt[++i] = ++k; else k = nxt[k]; } } void kmp(string s,string t) { int i = 0,j = 0,len = s.size(); while
(i < len) { if(j == -1 || s[i] == t[j]) { i++,j++; if(j == t.size()) vis[i-t.size()+1] = 1,j = nxt[j]; } else j = nxt[j]; } } int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); string s;cin >> s; string s1,s2;cin >> s1 >> s2; pre_next(s); kmp(s,s1); for(int i = 0;i < s.size();++i) vis[i] = vis[i+1]; string ans; for(int i = 0;i < s.size();++i) { if(vis[i]) { ans += s2; i = i+s1.size()-1; } else ans += s[i]; } cout << ans << endl; // system("pause"); return 0; }
View Code

A:小K的疑惑

以根節點為標記點,求出下面和它奇數距離的點,和偶數距離的點的個數。

可以發現,互相為奇數距離的點,肯定都在奇數距離點集中。

互相為偶數距離的點,肯定都是偶數距離的點集中。根節點看成到自己為0.

那麼ans = cnt1^3 + cnt2^3 (cnt1為奇數集合大小,cnt2為偶數)

為什麼是三次,因為可重複。那麼組合數應該是cnt1*cnt1*cnt1(第一位置可選cnt1個,第二位置也可選cnt1個,第三位置也可選cnt1個)

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef long double ld;
typedef pair<LL,int> pii;
const int N = 1e6+5;
const int M = 1e6+5;
const LL Mod = 998244353;
#define rg register
#define pi acos(-1)
#define INF 1e9
#define INM INT_MIN
#define dbg(ax) cout << "now this num is " << ax << endl;
inline int read()
{
    int x = 0,f = 1;char c = getchar();
    while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
    while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
    return x*f;
}
LL dp[N][2];//dp[i][0] - 向下偶數長度的點,dp[i][1] - 向下奇數長度的點
struct Node{int to,dis;};
vector<Node> G[N];
LL quick_mi(LL a,LL b)
{
    LL re = 1;
    while(b)
    {
        if(b&1) re = re*a;
        a = a*a;
        b >>= 1;
    }
    return re;
}
void dfs(int u,int fa)
{
    for(auto v : G[u])
    {
        if(v.to == fa) continue;
        dfs(v.to,u);
        if(v.dis%2)
        {
            dp[u][0] += dp[v.to][1];
            dp[u][1] += dp[v.to][0]+1;
        }
        else
        {
            dp[u][0] += dp[v.to][0]+1;
            dp[u][1] += dp[v.to][1];
        }
    }
}
int main()
{
    int n;n = read();
    for(rg int i = 1;i < n;++i)
    {
        int x,y,z;
        x = read(),y = read(),z = read();
        G[x].push_back(Node{y,z});
        G[y].push_back(Node{x,z});
    }
    dfs(1,0);
    dp[1][0]++;//加上根節點自己
    LL ans = quick_mi(dp[1][0],3)+quick_mi(dp[1][1],3);
    printf("%lld\n",ans);
   // system("pause");
    return 0;
}
View Code