Problem D. Euler Function
思路:打表找找规律。
#include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define pii pair<int,int> using namespace std; const int N=1e5+7; const int M=1e4+7; const int inf=0x3f3f3f3f; const LL INF=0x3f3f3f3f3f3f3f3f; const int mod=1e9 + 7; int n; int main() { int T; scanf("%d", &T); while(T--) { scanf("%d", &n); if(n == 1) { puts("5"); } else if(n == 2) { puts("7"); } else if(n == 3) { puts("8"); } else { printf("%d ", n + 5); } } return 0; }
Problem F. Grab The Tree
思路:把全部数字异或起来,看是不是0就行了,如果不是0,先手取最高位的那个。
#include<bits/stdc++.h> using namespace std; const int N = 100100; int main() { int T; scanf("%d",&T); while(T--) { int n;scanf("%d",&n); long long ans=0; for(int i=0;i<n;i++){ long long tt; scanf("%lld",&tt); ans^=tt; } for(int i=0;i<n-1;i++){ int l,r; scanf("%d%d",&l,&r); } if(ans==0) printf("D "); else printf("Q "); } } /* 2 3 2 2 2 1 2 1 3 */
Problem L. Visual Cube
思路:模拟画立方体。。
#include<bits/stdc++.h> using namespace std; int c,k,g; int mp[1000][1000]; void gz() { int y=c*2+k*2+1; int x=g*2+k*2+1; // printf("%d ",y); for(int i=0;i<2*k;i++) { for(int j=0;j<2*k-i;j++) mp[i][j]='.'; } int cnt=x-1; int ks=c*2; for(int i=0;i<2*k;i++) { for(int j=0;j<2*k-i;j++) mp[cnt][ks+j+1]='.'; ks++; cnt--; } for(int i=0;i<x;i++) { bool judge=true; for(int j=0;j<y;j++) { if(mp[i][j]=='.') continue; else if(judge){ judge=false; if(i%2==0){ int cnt=0; for(;;j+=2) { if(cnt==c) break; mp[i][j]='+'; mp[i][j+1]='-'; cnt++; } j--; } else{ int cnt=0; for(;;j+=2){ if(cnt==c) break; if(mp[i][0]=='.') mp[i][j]='/'; else mp[i][j]='|'; mp[i][j+1]='.'; cnt++; } j--; } } else{ if(i%2==0) { if(j==y-1) mp[i][j]='+'; else{ mp[i][j++]='+'; mp[i][j]='.'; } } else{ if(j%2) mp[i][j]='/'; else mp[i][j]='|'; } } } } for(int i=0;i<x;i++){ for(int j=0;j<y;j++){ printf("%c",mp[i][j]); }puts(""); } } int main() { int T; scanf("%d",&T); while(T--) { memset(mp,0,sizeof(mp)); scanf("%d%d%d",&c,&k,&g); gz(); } }
Problem A. Ascending Rating
思路:正常思路应该是倒着维护单调递减的队列就好啦,然后我正着扫暴力搞的。。
#include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define pii pair<int,int> using namespace std; const int N=1e7+7; const int M=1e4+7; const int inf=0x3f3f3f3f; const LL INF=0x3f3f3f3f3f3f3f3f; int n, m, k, p, q, r, a[N], mod, stk[N << 1], head, rear, stk2[N], tot, rt[N]; int main() { int T; scanf("%d", &T); while(T--) { head = 10000001, rear = 10000000, tot = 0; scanf("%d%d%d%d%d%d%d", &n, &m, &k, &p, &q, &r, &mod); for(int i = 1; i <= k; i++) scanf("%d", &a[i]); a[n + 1] = inf; for(int i = k + 1; i <= n; i++) a[i] = (1ll * p * a[i - 1] + 1ll * q * i + r) % mod; stk2[++tot] = n + 1; for(int i = n; i >= 1; i--) { while(a[stk2[tot]] <= a[i]) tot--; rt[i] = stk2[tot]; stk2[++tot] = i; } for(int i = 1; i <= m; i++) { if(a[i] > 0 && (rear < head || a[i] > a[stk[rear]])) stk[++rear] = i; } // printf("%d: %d %d ", 1, a[stk[rear]], rear - head + 1); LL A = 0, B = 0; if(rear >= head) { A += a[stk[rear]] ^ 1; B += (rear - head + 1) ^ 1; } else { A += 0 ^ 1; B += 0 ^ 1; } for(int i = 2; i <= n - m + 1; i++) { int j = i + m - 1; if(a[j] > 0 && (rear < head || a[j] > a[stk[rear]])) stk[++rear] = j; if(head <= rear && stk[head] < i) { int down = i, up = j; tot = 0; if(rear > head) up = stk[head + 1] - 1; while(down <= up) { if(a[down] > 0) stk2[++tot] = down; down = rt[down]; } head++; for(int w = tot; w >= 1; w--) stk[--head] = stk2[w]; } // puts(""); // for(int w = head; w <= rear; w++) printf("%d ", stk[w]); // puts(""); if(rear >= head) { A += a[stk[rear]] ^ i; B += (rear - head + 1) ^ i; } else { A += 0 ^ i; B += 0 ^ i; } } // cout << ans << endl; printf("%lld %lld ", A, B); } return 0; } /* 1 10 6 10 5 5 5 5 0 0 0 0 0 0 0 0 0 0 */
Problem C. Dynamic Graph Matching
思路:状压dp,没加进一条边或者删掉一条边,用dp维护这个过程。
#include<bits/stdc++.h> #define fi first #define se second #define mp make_pair #define pb push_back #define pi acos(-1.0) #define ll long long #define vi vector<int> #define mod 1000000007 #define ld long double #define C 0.5772156649 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 #define pll pair<ll,ll> #define pil pair<int,ll> #define pli pair<ll,int> #define pii pair<int,int> #define cd complex<double> #define ull unsigned long long #define base 1000000000000000000 #define Max(a,b) ((a)>(b)?(a):(b)) #define Min(a,b) ((a)<(b)?(a):(b)) #define fio ios::sync_with_stdio(false);cin.tie(0) template<typename T> inline T const& MAX(T const &a,T const &b){return a>b?a:b;} template<typename T> inline T const& MIN(T const &a,T const &b){return a<b?a:b;} inline void add(ll &a,ll b){a+=b;if(a>=mod)a-=mod;} inline void sub(ll &a,ll b){a-=b;if(a<0)a+=mod;} inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;} inline ll qp(ll a,ll b){ll ans=1;while(b){if(b&1)ans=ans*a%mod;a=a*a%mod,b>>=1;}return ans;} inline ll qp(ll a,ll b,ll c){ll ans=1;while(b){if(b&1)ans=ans*a%c;a=a*a%c,b>>=1;}return ans;} using namespace std; const double eps=1e-8; const ll INF=0x3f3f3f3f3f3f3f3f; const int N=1024+10,maxn=10+10,inf=0x3f3f3f3f; ll ans[maxn],dp[N]; int n,m; inline int read() { char ch = getchar(); int x = 0, f = 1; while(ch < '0' || ch > '9') { if(ch == '-') f = -1; ch = getchar(); } while('0' <= ch && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } return x * f; } int main() { int T=read(); while(T--) { memset(dp, 0, sizeof(dp)); n=read(),m=read(); dp[0] = 1; int up = 1 << n; for(int i=0;i<m;i++) { memset(ans,0,sizeof ans); char op[2];int u,v; scanf("%s",op);u=read(),v=read(); u--, v--; if(op[0]=='+') { for(int s = 0; s < up; s++) { if(((s >> u) & 1) || ((s >> v) & 1)) continue; int nxs = s | (1 << u) | (1 << v); dp[nxs] += dp[s]; if(dp[nxs] >= mod) dp[nxs] -= mod; } } else { for(int s = 0; s < up; s++) { if(((s >> u) & 1) || ((s >> v) & 1)) continue; int nxs = s | (1 << u) | (1 << v); dp[nxs] -= dp[s]; if(dp[nxs] < 0) dp[nxs] += mod; } } for(int s = 1; s < up; s++) { int S = s, cnt = 0; while(S) { cnt++; S -= S & -S; } ans[cnt / 2] += dp[s]; if(ans[cnt / 2] >= mod) ans[cnt / 2] -= mod; } for(int j=1;j<n/2;j++) printf("%lld ",ans[j]); printf("%lld ",ans[n/2]); } } return 0; }
补题**************************************************************
Problem G. Interstellar Travel
思路:求个上凸包的同时维护字典序最小。 比赛的时候没有调出来。。。
#include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define pii pair<int,int> #define pLL pair<long long, long long> #define piii pair<int, pair<int,int>> using namespace std; const int N=2e5 + 7; const int M=1e4 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 + 7; const double eps = 1e-10; const double PI = acos(-1); int n, cnt, tot; map<pLL, bool> mp; struct Point { LL x, y; int id; Point(LL x = 0, LL y = 0) : x(x), y(y) { } }p[N], ch[N]; typedef Point Vector; Point operator + (Vector A, Vector B) {return Point(A.x + B.x, A.y + B.y);} Point operator - (Vector A, Vector B) {return Point(A.x - B.x, A.y - B.y);} bool operator == (const Vector &A, const Point &B) {return A.x - B.x == 0 && A.y - B.y == 0;} bool operator < (const Vector &A, const Vector &B) {return A.x < B.x || (A.x == B.x && A.y < B.y);} LL Cross(Vector A, Vector B) {return A.x * B.y - A.y * B.x;} bool check(int m, int i) { LL val = Cross(ch[m - 1] - ch[m - 2], p[i] - ch[m - 2]); if(val > 0 || val == 0 && p[i].id < ch[m - 1].id) return true; return false; } int ConvexHull(Point *p, int n, Point *ch) { sort(p, p + n); int m = 0; for(int i = 0; i < n; i++) { while(m > 1 && check(m, i)) m--; ch[m++] = p[i]; } return m; } int main() { int T; scanf("%d", &T); while(T--) { mp.clear(); tot = 0; cnt = 0; scanf("%d", &n); for(int i = 0; i < n; i++) { LL x, y; scanf("%lld%lld", &x, &y); if(mp.find(mk(x, y)) == mp.end()) { p[tot].x = x; p[tot].y = y; p[tot++].id = i + 1; mp[mk(x, y)] = true; } } cnt = ConvexHull(p, tot, ch); printf("%d", ch[0].id); for(int i = 1; i < cnt; i++) { printf(" %d", ch[i].id); } puts(""); } return 0; } /* 1 9 1 0 4 2 5 2 3 2 2 1 6 2 7 1 6 2 8 0 1 9 */
Problem I. Random Sequence
思路:dp[ i ][ v1 ][ v2 ][ v3 ]表示到第 i 个数, a[ i ] 为 v1, gcd(a[ i ], a[ i - 1 ]) = v2,gcd(a[ i ], a[ i - 1 ], a[ i - 2 ]) = v3的期望
因为v3|v2 v2|v1所以状态数不是很多可以预处理一些东西然后直接转移。
#include<bits/stdc++.h> #define LL long long #define ll long long #define fi first #define se second #define mk make_pair #define pii pair<int, int> #define y1 skldjfskldjg #define y2 skldfjsklejg using namespace std; const int N = 100 + 7; const int M = 1e5 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const LL mod = 1e9 + 7; const int maxn = 1e5; int n, m, cur, a[N], v[N], f[2][N][N][N], gcd[N][N], d[N][N], inv[N]; void init() { for(int i = 0; i <= 100; i++) gcd[i][0] = gcd[0][i] = i; for(int i = 1; i <= 100; i++) for(int j = 1; j <= i; j++) gcd[i][j] = gcd[j][i] = gcd[j][i % j]; inv[1] = 1; for(int i = 2; i <= 100; i++) inv[i] = 1ll * (mod - mod / i) * inv[mod % i] % mod; for(int i = 1; i <= 100; i++) { d[i][0] = 0; for(int j = 1; j <= i; j++) if(i % j == 0) d[i][++d[i][0]] = j; } } void add(int &a, int b) { a += b; if(a >= mod) a -= mod; } int main() { init(); int T; scanf("%d", &T); while(T--) { scanf("%d%d", &n, &m); for(int i = 1; i <= n; i++) scanf("%d", &a[i]); for(int i = 1; i <= m; i++) scanf("%d", &v[i]); memset(f, 0, sizeof(f)); if(a[1]) { f[cur][a[1]][a[1]][a[1]] = 1; } else { for(int i = 1; i <= m; i++) f[cur][i][i][i] = inv[m]; } for(int i = 2; i <= n; i++) { cur ^= 1; for(int j = 1; j <= m; j++) { for(int k = 1; k <= d[j][0]; k++) { int v2 = d[j][k]; for(int z = 1; z <= d[v2][0]; z++) { int v3 = d[v2][z]; f[cur][j][v2][v3] = 0; } } } for(int j = 1; j <= m; j++) { for(int k = 1; k <= d[j][0]; k++) { int v2 = d[j][k]; for(int z = 1; z <= d[v2][0]; z++) { int v3 = d[v2][z]; int val = f[cur ^ 1][j][v2][v3]; if(a[i]) { if(i <= 3) add(f[cur][a[i]][gcd[a[i]][j]][gcd[a[i]][v2]], val); else add(f[cur][a[i]][gcd[a[i]][j]][gcd[a[i]][v2]], 1ll * val * v[gcd[a[i]][v3]] % mod); } else { val = 1ll * val * inv[m] % mod; for(int t = 1; t <= m; t++) { if(i <= 3) add(f[cur][t][gcd[t][j]][gcd[t][v2]], val); else add(f[cur][t][gcd[t][j]][gcd[t][v2]], 1ll * val * v[gcd[t][v3]] % mod); } } } } } } int ans = 0; for(int j = 1; j <= m; j++) { for(int k = 1; k <= d[j][0]; k++) { int v2 = d[j][k]; for(int z = 1; z <= d[v2][0]; z++) { int v3 = d[v2][z]; add(ans, f[cur][j][v2][v3]); } } } printf("%d ", ans); } return 0; } /* */
Problem M. Walking Plan
思路:将步数分块,dp[ A ][ i ][ j ]表示刚好用A * 100步从i - > j 所需要的最小消耗,
dis[ B ][ i ][ j ]表示至少用B步从 i - > j所需要的最小消耗。
对于一个询问S, T, K来说 ans = min{dp[ K / 100 ][ S ][ i ] + dis[ K % 100 ][ i ][ T ]} 1 <= i <= n
#include<bits/stdc++.h> #define LL long long #define ll long long #define fi first #define se second #define mk make_pair #define pii pair<int, int> #define y1 skldjfskldjg #define y2 skldfjsklejg using namespace std; const int N = 50 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const LL mod = 1e9 + 7; const int maxn = 1e5; int n, m, dis[202][N][N], Map[N][N]; struct Matrix { int r, c; int a[51][51]; Matrix(int r = 0, int c = 0) { this -> r = r; this -> c = c; for(int i = 0; i < r; i++) for(int j = 0; j < c; j++) a[i][j] = inf; } Matrix operator * (const Matrix &B) const { Matrix C(r, c); for(int i=0;i<r;i++) for(int j=0;j<c;j++) for(int k=0;k<r;k++) C.a[i][j] = min(C.a[i][j], a[i][k] + B.a[k][j]); return C; } } M[101]; int main() { int T; scanf("%d", &T); while(T--) { memset(dis, inf, sizeof(dis)); memset(Map, inf, sizeof(Map)); scanf("%d%d", &n, &m); for(int i = 0; i < n; i++) { Map[i][i] = 0; dis[0][i][i] = 0; } for(int i = 1; i <= m; i++) { int u, v, w; scanf("%d%d%d", &u, &v, &w); u--, v--; Map[u][v] = min(Map[u][v], w); dis[1][u][v] = min(dis[1][u][v], Map[u][v]); } for(int k = 2; k <= 201; k++) { for(int i = 0; i < n; i++) { for(int j = 0; j < n; j++) { for(int z = 0; z < n; z++) { dis[k][i][j] = min(dis[k][i][j], dis[k - 1][i][z] + dis[1][z][j]); } } } } for(int i = 1; i <= 100; i++) M[i].r = M[i].c = n; for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) M[1].a[i][j] = dis[100][i][j], M[0].a[i][j] = dis[0][i][j]; for(int k = 200; k >= 0; k--) for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) dis[k][i][j] = min(dis[k][i][j], dis[k + 1][i][j]); for(int i = 2; i <= 100; i++) { M[i] = M[i - 1] * M[1]; } int q; scanf("%d", &q); while(q--) { int S, T, K; scanf("%d%d%d", &S, &T, &K); S--, T--; int id1 = K / 100, id2 = K % 100; int ans = inf; for(int i = 0; i < n; i++) { ans = min(ans, M[id1].a[S][i] + dis[id2][i][T]); } if(ans == inf) puts("-1"); else printf("%d ", ans); } } return 0; } /* */