首页 > 代码库 > ACM ICPC Vietnam National Second Round
ACM ICPC Vietnam National Second Round
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$的情况,以后对于取模的题,在输出之前一定要取模保险。
ACM ICPC Vietnam National Second Round
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。