前言:高处不胜寒,但贵在坚守。
Divisibility
题解上都是从结论出发去证明的。但我觉得一开始不可能都知道结论。所以稍微从思考角度出发
可以发现$y = c1* b^{n-1} + c2 * b^{n-2} + ... + cn * b^{0}$
那么对于无限的f(y)操作,可以发现每次都是将所有位数加后重构继续加后重构。
那么可以看成对x各位相加后的取模操作。
那么题目就可以转化成:
是否同时满足:
$(c1* b^{n-1} + c2 * b^{n-2} + ... + cn * b^{0}) \equiv 0 mod (x)$时,
也满足 $(c1 + c2 + ... + cn ) \equiv 0 mod (x)$.
可以发现的是b = 1时,满足两式相等,那么肯定性质相同。
即可以发现b mod x == 1时,可以使两式相等,永远满足。
当b mod x != 1时。
证明:
如果b < x,那么显然不行,可以构造一个x的倍数,然后x的倍数最终会被转化到 < x。此时无法满足性质相同。
如果b >= x.令 $y = 0+0+....1*b^{1}+x-1$.
若$b+x-1 \equiv 0 (mod x)$
即$b \equiv 1 (mod x)$
因为b mod x != 1,所以矛盾,无法满足。

#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef long double ld; typedef pair<int,int> pii; const int N = 1e5+5; const int M = 1e6+5; const LL Mod = 1e9+7; #define rg register #define pi acos(-1) #define INF 1e18 #define INM INT_MIN #define dbg(ax) cout << "now this num is " << ax << endl; inline LL read() { LL 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 main() { int ca;ca = read(); while(ca--) { LL b,x;b = read(),x = read(); if(b%x == 1) printf("T\n"); else printf("F\n"); } system("pause"); return 0; }
Little Rabbit's Equation
难度最低的一个题吧。(进制转换对我来说还是很难受)
考虑这么多种进制会很难处理,那么将所有数都转化为10进制即可(注意这里最大15位数,所以开longlong)
记一下进制转换:将其他进制转换为10进制,以该进制为基数来模拟10进制+来实现转化。
注意的是,如果当前值>=进制,那么说明这个数不属于这个进制,那么次时查找肯定无效。
PS:printf和cin混用导致debug了蛮久。。

#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef long double ld; typedef pair<int,int> pii; const LL N = 2e14+5; const int M = 1005; const LL Mod = 1e9+7; #define rg register #define pi acos(-1) #define INF 1e9 #define INM INT_MIN #define dbg(ax) cout << "now this num is " << ax << endl; unordered_map<char,LL> mp; void init() { mp['0'] = 0,mp['1'] = 1,mp['2'] = 2,mp['3'] = 3,mp['4'] = 4,mp['5'] = 5; mp['6'] = 6,mp['7'] = 7,mp['8'] = 8,mp['9'] = 9,mp['A'] = 10,mp['B'] = 11; mp['C'] = 12,mp['D'] = 13,mp['E'] = 14,mp['F'] = 15; } int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); init(); string s; while(cin >> s) { int flag = 0; for(int ba = 2;ba <= 16;++ba) { LL a = 0,b = 0,c = 0,t = 0; int id,tag = 0; for(int i = 0;i < s.size();++i) { if(s[i] == '+') a = t,t = 0,id = 1; else if(s[i] == '-') a = t,t = 0,id = 2; else if(s[i] == '*') a = t,t = 0,id = 3; else if(s[i] == '/') a = t,t = 0,id = 4; else if(s[i] == '=') b = t,t = 0; else { if(mp[s[i]] >= ba){tag = 1;break;} t = t*ba+mp[s[i]]; } } if(tag) continue; c = t; // printf("a is %lld b is %lld c is %lld\n",a,b,c); if(id == 1 && a+b == c) flag = ba; if(id == 2 && a-b == c) flag = ba; if(id == 3 && a*b == c) flag = ba; if(id == 4 && b*c == a) flag = ba; if(flag) break; } if(flag) cout << flag << endl; else cout << "-1" << endl; } system("pause"); return 0; }
Road To The 3rd Building
可以发现的是,对于长度一样的组合,他们的长度是一样的。
那么记录下前缀和即可。
这里由于取模后sum[n-i+1]可能会<sum[i-1],所以要加模数防负数。

#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef long double ld; typedef pair<int,int> pii; const int N = 2e5+5; const int M = 1e6+5; const LL Mod = 1e9+7; #define rg register #define pi acos(-1) #define INF 1e18 #define INM INT_MIN #define dbg(ax) cout << "now this num is " << ax << endl; inline LL read() { LL 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 quick_mi(LL a,LL b) { LL re = 1; a %= Mod; while(b) { if(b&1) re = (re*a)%Mod; a = (a*a)%Mod; b >>= 1; } return re; } LL sum[N],a[N]; int main() { int ca;ca = read(); while(ca--) { LL n;n = read(); memset(sum,0,sizeof(sum)); for(int i = 1;i <= n;++i) a[i] = read(),sum[i] = (sum[i-1]+a[i])%Mod; LL ans = 0,pre = 0; for(int i = 1;i <= n/2;++i) { pre = (pre+(sum[n-i+1]-sum[i-1])%Mod+Mod)%Mod; ans = (ans+pre*quick_mi(i,Mod-2)%Mod)%Mod; ans = (ans+pre*quick_mi(n-i+1,Mod-2)%Mod)%Mod; } if(n%2 == 1) { pre = (pre+a[n/2+1])%Mod; ans = (ans+pre*quick_mi(n/2+1,Mod-2)%Mod)%Mod; } LL ma = n*(n+1)/2; ans = ans*quick_mi(ma,Mod-2)%Mod; printf("%lld\n",ans); } system("pause"); return 0; }
A Very Easy Graph Problem
递推了一个小时终于递推出了(i,j)可轮换的换根dp的转移式。
结果一看题不可轮换,人傻了。。(先记录一下,毕竟是努力的结果)
可轮换代码:

#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef long double ld; typedef pair<int,int> pii; const int N = 1e5+5; const int M = 1e6+5; const LL Mod = 1e9+7; #define rg register #define pi acos(-1) #define INF 1e18 #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; } struct Node{int to;LL dis;}; vector<Node> G[N]; int n,m,a[N],fa[N]; LL dp[N][2],num[N][2],cnt1 = 0,cnt0 = 0;//num[2][0]-向下有多少0点,num[2][1]-1点,dp[2][0]向下的0的距离总和,dp[2][1]向下的1距离总和 int Find(int x) { return x == fa[x] ? x : fa[x] = Find(fa[x]); } LL quick_mi(LL a,LL b) { LL re = 1; a %= Mod; while(b) { if(b&1) re = (re*a)%Mod; a = (a*a)%Mod; b >>= 1; } return re; } LL inv(LL n){return quick_mi(n,Mod-2)%Mod;} void dfs(int u,int fa) { if(a[u] == 1) num[u][1] = 1; else num[u][0] = 1; for(auto v : G[u]) { if(v.to == fa) continue; dfs(v.to,u); num[u][0] += num[v.to][0]; num[u][0] %= Mod; num[u][1] += num[v.to][1]; num[u][1] %= Mod; dp[u][0] = (dp[u][0]+dp[v.to][0]+(num[v.to][0]*v.dis)%Mod)%Mod; dp[u][1] = (dp[u][1]+dp[v.to][1]+(num[v.to][1]*v.dis)%Mod)%Mod; } } void dfs1(int u,int fa,LL dis) { if(fa != 0) { dp[u][1] = (dp[u][1]+((dp[fa][1]-dp[u][1]-num[u][1]*dis%Mod)+Mod)%Mod+((cnt1-num[u][1])+Mod)%Mod*dis%Mod)%Mod; dp[u][1] = (dp[u][1]+Mod)%Mod; dp[u][0] = (dp[u][0]+((dp[fa][0]-dp[u][0]-num[u][0]*dis%Mod)+Mod)%Mod+((cnt0-num[u][0])+Mod)%Mod*dis%Mod)%Mod; dp[u][0] = (dp[u][0]+Mod)%Mod; } for(auto v : G[u]) { if(v.to == fa) continue; dfs1(v.to,u,v.dis); } } int main() { int t;t = read(); while(t--) { n = read(),m = read(); memset(dp,0,sizeof(dp)); memset(num,0,sizeof(num)); cnt1 = cnt0 = 0; for(int i = 1;i <= n;++i) { a[i] = read(),G[i].clear(),fa[i] = i; if(a[i] == 1) cnt1++; else cnt0++; } for(int i = 1;i <= m;++i) { int u,v;u = read(),v = read(); int xx = Find(u),yy = Find(v); if(xx != yy) { fa[xx] = yy; G[u].push_back(Node{v,quick_mi(2,i)}); G[v].push_back(Node{u,quick_mi(2,i)}); } } dfs(1,0); dfs1(1,0,0); LL ans = 0; for(int i = 1;i <= n;++i) printf("i is %d 0 is %lld 1 is %lld\n",i,dp[i][0],dp[i][1]); for(int i = 1;i <= n;++i) ans = (ans+dp[i][a[i]^1])%Mod; printf("%lld\n",ans); } system("pause"); return 0; }
正解:
可以发现,这个图并不是一个树。
但是,我们要的距离是最短距离,那么可以在输入的时候去维护一棵最小的生成树。
因为满足$2^{i} > 2^{i-1} + 2^{i-2} + ... 2^{1}$
那么我们选择越前面的边,显然代价越小。
那么就可以维护输入顺序的最小生成树即可。
如何统计答案,因为是不可轮换式的。
那么我们可以去统计每条边对答案的贡献。
所以我们dfs处理出每个点下面的0,1的数量(包括该点)。
然后对于一条边的贡献就是他一边的1的数量*另一边的0的数量*该边的权值 (即num1 * num0 * cost) .还有 0 * 1 * cost

#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef long double ld; typedef pair<int,int> pii; const int N = 1e5+5; const int M = 1e6+5; const LL Mod = 1e9+7; #define rg register #define pi acos(-1) #define INF 1e18 #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; } struct Node{int to;LL dis;}; vector<Node> G[N]; int n,m,a[N],fa[N]; LL num[N][2],ans,cnt1,cnt0; int Find(int x) { return x == fa[x] ? x : fa[x] = Find(fa[x]); } LL quick_mi(LL a,LL b) { LL re = 1; while(b) { if(b&1) re = (re*a)%Mod; a = (a*a)%Mod; b >>= 1; } return re; } void dfs(int u,int fa) { num[u][a[u]] = 1; for(auto v : G[u]) { if(v.to == fa) continue; dfs(v.to,u); num[u][0] += num[v.to][0]; num[u][0] %= Mod; num[u][1] += num[v.to][1]; num[u][1] %= Mod; } } void dfs1(int u,int fa,LL dis) { if(fa != 0) { ans = (ans+dis*((num[u][0])*(cnt1-num[u][1])%Mod)%Mod)%Mod; ans = (ans+dis*((num[u][1])*(cnt0-num[u][0])%Mod)%Mod)%Mod; } for(auto v : G[u]) { if(v.to == fa) continue; dfs1(v.to,u,v.dis); } } int main() { int t;t = read(); while(t--) { n = read(),m = read(); memset(num,0,sizeof(num)); ans = cnt1 = cnt0 = 0; for(int i = 1;i <= n;++i) { a[i] = read(),G[i].clear(),fa[i] = i; if(a[i] == 1) cnt1++; else cnt0++; } for(int i = 1;i <= m;++i) { int u,v;u = read(),v = read(); int xx = Find(u),yy = Find(v); if(xx != yy) { fa[xx] = yy; G[u].push_back(Node{v,quick_mi(2,i)}); G[v].push_back(Node{u,quick_mi(2,i)}); } } dfs(1,0); dfs1(1,0,0); printf("%lld\n",ans); } system("pause"); return 0; }