《牛客演算法周練18》
阿新 • • 發佈:2020-08-05
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 #defineView Codedbg(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; }
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