首页 > 代码库 > 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