《華東交通大學2018年ACM“雙基”程式設計競賽*補》
阿新 • • 發佈:2020-08-09
A:
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef long double ld; typedef pair<int,int> pii; const int N = 205; 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; inlineView Codeint 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 main() { cout << "ecjtuacm" << "\n";//system("pause"); return 0; }
B:
因為n很小,可以直接遞推。
但是也可以矩陣快速冪遞推。
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef long double ld; typedef pair<int,int> pii; const int N = 1e3+5; const int M = 5e4+5; const LL Mod = 1e9+7; #define rg register #define pi acos(-1) #defineView CodeINF 1e9 #define INM INT_MIN #define dbg(ax) cout << "now this num is " << ax << endl; struct Mat{ LL m[5][5]; Mat operator * (const Mat &a)const{ Mat c;memset(c.m,0,sizeof(c.m)); for(int i = 0;i < 4;++i) for(int j = 0;j < 4;++j) for(int k = 0;k < 4;++k) c.m[i][j] = (c.m[i][j]+m[i][k]*a.m[k][j]%Mod)%Mod; return c; } }; LL ta[5][5] = { {2,3,1,1}, {1,0,0,0}, {0,0,1,1}, {0,0,0,1}, }; Mat Mat_qm(Mat a,LL b) { Mat res;memset(res.m,0,sizeof(res.m)); for(int i = 0;i < 5;++i) res.m[i][i] = 1; while(b) { if(b&1) res = res*a; a = a*a; b >>= 1; } return res; } int main() { ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); int n; while(cin >> n,n) { Mat ans;memset(ans.m,0,sizeof(ans.m)); for(int i = 0;i < 5;++i) for(int j = 0;j < 5;++j) ans.m[i][j] = ta[i][j]; if(n == 1) printf("1\n"); else if(n == 2) printf("2\n"); else { ans = Mat_qm(ans,n-2); LL sum = 0; sum = (sum+2*ans.m[0][0])%Mod; sum = (sum+1*ans.m[0][1])%Mod; sum = (sum+2*ans.m[0][2])%Mod; sum = (sum+1*ans.m[0][3])%Mod; printf("%lld\n",sum); } } // system("pause"); return 0; }
C:
顯然是矩陣快速冪。
把f[n]轉換到f[n-1]和f[n-2]。那麼就可以變形為。
$g[n+1] = g[n] + 2f[n] + 3f[n-1] + n^2 + 3n + 2n^0$注意常數項看成0次。
矩陣快速冪遞推即可。
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef long double ld; typedef pair<int,int> pii; const int N = 1e3+5; const int M = 5e4+5; 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; struct Mat{ LL m[10][10]; Mat operator * (const Mat &a)const{ Mat c;memset(c.m,0,sizeof(c.m)); for(int i = 0;i < 6;++i) for(int j = 0;j < 6;++j) for(int k = 0;k < 6;++k) c.m[i][j] = (c.m[i][j]+m[i][k]*a.m[k][j]%Mod)%Mod; return c; } }; LL ta[10][10] = { {1,2,3,1,3,2}, {0,2,3,0,1,1}, {0,1,0,0,0,0}, {0,0,0,1,2,1}, {0,0,0,0,1,1}, {0,0,0,0,0,1}, }; Mat Mat_qm(Mat a,LL b) { Mat res;memset(res.m,0,sizeof(res.m)); for(int i = 0;i < 6;++i) res.m[i][i] = 1; while(b) { if(b&1) res = res*a; a = a*a; b >>= 1; } return res; } int main() { ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); LL n; while(cin >> n,n) { if(n == 1) printf("2\n"); else if(n == 2) printf("8\n"); else { Mat ans;memset(ans.m,0,sizeof(ans.m)); for(int i = 0;i < 6;++i) for(int j = 0;j < 6;++j) ans.m[i][j] = ta[i][j]; ans = Mat_qm(ans,n-2); LL sum = 0; sum = (sum+ans.m[0][0]*8%Mod)%Mod; sum = (sum+ans.m[0][1]*2%Mod)%Mod; sum = (sum+ans.m[0][2]*1%Mod)%Mod; sum = (sum+ans.m[0][3]*4%Mod)%Mod; sum = (sum+ans.m[0][4]*2%Mod)%Mod; sum = (sum+ans.m[0][5]*1%Mod)%Mod; printf("%lld\n",sum); } } // system("pause"); return 0; }View Code
D:
注意,拿走了一張牌後,對於這張牌另一個人不可能拿到。
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef long double ld; typedef pair<int,int> pii; const int N = 205; const int M = 1e6+5; 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; 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 main() { int a,b; while(~scanf("%d %d",&a,&b),a != -1 && b != -1) { if(a == 0) printf("%s\n",b == 1 ? "owatta" : "1"); else { int ma,all = 42; if(b == 1) ma = 21-a; else ma = 20+a-1; ma++; int gcd = __gcd(ma,all); ma /= gcd,all /= gcd; printf("%d/%d\n",ma,all); } } // system("pause"); return 0; }View Code
G:
數位dp
可以發現,如果這個數滿足是777...的倍數並且是數位和是777....的倍數。
那麼他肯定滿足時是7的倍數且數位和是7的倍數。
那麼我們用dp[i][10][10]來表示到了i位時,這個數對7取模和數位和對7取模。
這裡從最高位dp到最低位,我們最先會遍歷完所有情況,滿足數位dp的思想。
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef long double ld; typedef pair<int,int> pii; const int N = 1e3+5; const int M = 5e4+5; 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; LL dp[20][10][10],n,m; int a[20]; LL dfs(int pos,int sum1,int sum2,bool limit) { if(pos == 0) return (sum1 % 7 == 0 && sum2 % 7 == 0) ? 1 : 0; if(!limit && dp[pos][sum1][sum2] != -1) return dp[pos][sum1][sum2]; int up = limit ? a[pos] : 9; LL ans = 0; for(int i = 0;i <= up;++i) { ans += dfs(pos-1,(sum1*10+i)%7,(sum2+i)%7,limit && i == a[pos]); } if(!limit) dp[pos][sum1][sum2] = ans; return ans; } LL slove(LL x) { int len = 0; while(x) { a[++len] = x%10; x /= 10; } return dfs(len,0,0,true); } int main() { memset(dp,-1,sizeof(dp)); while(scanf("%lld %lld",&n,&m),n || m) { printf("%lld\n",slove(m)-slove(n-1)); } // system("pause"); return 0; }View Code
I:
有尤拉定理擴充套件:對於一個數,與其互質的數的總和總是euler(n)*n/2(注意是在1~n範圍內的數)
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef long double ld; typedef pair<int,int> pii; const int N = 205; const int M = 1e6+5; 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; 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 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; } LL euler(LL n) { LL ans = n; LL m = sqrt(n); for(LL i = 2;i <= m;++i) { if(n%i == 0) { ans = ans/i*(i-1); while(n%i == 0) n /= i; } } if(n != 1) ans = ans/n*(n-1); return ans; } int main() { LL n; while(~scanf("%lld",&n)) { if(n == 1) printf("0\n"); else { LL inv = quick_mi(2,Mod-2); LL ma1 = (((n%Mod)*((n+1)%Mod))%Mod*inv%Mod+Mod)%Mod; LL ma2 = (((euler(n)%Mod)*(n%Mod))%Mod*inv%Mod+Mod)%Mod; LL ans = (ma1-ma2+Mod)%Mod; printf("%lld\n",ans); } } //system("pause"); return 0; }View Code
J:
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef long double ld; typedef pair<int,int> pii; const int N = 205; const int M = 1e6+5; 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; 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 a[15]; int main() { while(cin >> a[1]) { for(int i = 2;i <= 10;++i) a[i] = read(); int s = 1; for(int i = 1;i <= 10;++i) { if(a[i] == 1) { if(s != 5) s++; } else if(a[i] == 7) { if(s != -1) s--; } } if(s >= 5) printf("666\n"); else printf("777\n"); } // system("pause"); return 0; }View Code
K:
最短路模改下就行
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef long double ld; typedef pair<int,int> pii; const int N = 205; 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 n,m,dis[N];//dis[i]到i需要的最少花費 struct Node{int to,dis;}; vector<Node> G[N]; void slove() { for(int i = 1;i <= n;++i) dis[i] = INF; dis[1] = 0; priority_queue<pii,vector<pii>,greater<pii> > Q; Q.push(pii{dis[1],1}); while(!Q.empty()) { int u = Q.top().second; int d = Q.top().first; Q.pop(); if(d > dis[u]) continue; for(auto v : G[u]) { if(dis[v.to] > max(dis[u],v.dis)) { dis[v.to] = max(dis[u],v.dis); Q.push(pii{dis[v.to],v.to}); } } } } int main() { while(~scanf("%d %d",&n,&m)) { for(int i = 1;i <= n;++i) G[i].clear(); while(m--) { int x,y,z; x = read(),y = read(),z = read(); G[x].push_back(Node{y,z}); } slove(); printf("%d\n",dis[n]); } //system("pause"); return 0; }View Code