1. 程式人生 > >51nod 1501 石頭剪刀布威力加強版

51nod 1501 石頭剪刀布威力加強版

開始 ges 復雜 open 石頭 oid chan -- def

技術分享

分析:很容易想到lcm(n,m)是個周期。不妨設n<=m,設k=a*lcm+b*n+c, (0<=b*n<lcm,0<=c<n),記g=gcd(n,m),然後枚舉數字num=0,1,2,枚舉i=0,1,...,g-1,然後從i開始以n為步長走,直到回到原地,就得到了坐標為j*n+i的所有點走一個周期對答案的貢獻。

然後就是a數組以n為步長在b數組上平移,共移b-1次,可以dp做一下,類似前面的思路,還是枚舉數字,然後枚舉余數,最後c次直接模擬即可,全部加起來就是答案了。

復雜度是O(n+m)的。。然而。。1015ms T了。。。改成C就變成500+ms了。。orz

  1 #include<stdio.h>
  2
#define SWAP(x,y){ll t=x;x=y;y=t;} 3 #define ll long long 4 const int maxn=5e5+5; 5 int x[maxn],y[maxn]; 6 ll W[3][maxn],L[3][maxn]; 7 ll w[3][maxn]={0,0,0},l[3][maxn]={0,0,0}; 8 inline int Score(int a,int b){ 9 if(a==b)return 0; 10 if((a+1)%3==b)return 1; 11 return -1; 12 } 13
int gcd(int a,int b){ 14 return b==0?a:gcd(b,a%b); 15 } 16 ll n,m; 17 ll testw,testl; 18 void test(int k){ 19 testw=0;testl=0; 20 for(int i=0;i<k;i++){ 21 int s0=Score(x[i%n],y[i%m]); 22 if(s0==1)testw++; 23 else if(s0==-1)testl++; 24 } 25 } 26 int main(){
27 // freopen("e:\\in.txt","r",stdin); 28 int Is_exchange=0; 29 ll k; 30 scanf("%lld%lld%lld",&n,&m,&k); 31 if(n>m){ 32 Is_exchange=1; 33 for(int i=0;i<n;i++)scanf("%d",&y[i]); 34 for(int i=0;i<m;i++)scanf("%d",&x[i]); 35 SWAP(n,m); 36 }else{ 37 for(int i=0;i<n;i++)scanf("%d",&x[i]); 38 for(int i=0;i<m;i++)scanf("%d",&y[i]); 39 } 40 // test(k); 41 ll g=gcd(n,m); 42 ll lcm=(ll)n*m/g; 43 ll a=k/lcm; 44 int b=(k%lcm)/n; 45 ll c=k%n; 46 for(int num=0;num<3;num++){ 47 for(int h=0;h<g;h++){ 48 for(int i=0;i<b;i++){ 49 int s0=Score(num,y[(h+i*n)%m]); 50 if(s0==1)W[num][h]++; 51 else if(s0==-1)L[num][h]++; 52 } 53 w[num][h]=W[num][h]; 54 l[num][h]=L[num][h]; 55 for(int i=b;i<lcm/n;i++){ 56 int s0=Score(num,y[(h+i*n)%m]); 57 if(s0==1)w[num][h]++; 58 else if(s0==-1)l[num][h]++; 59 } 60 int idx_last=h,idx_next=(h+b*n)%m; 61 for(int s=(h+n)%m;s!=h;s=(s+n)%m){ 62 W[num][s]=W[num][idx_last]; 63 L[num][s]=L[num][idx_last]; 64 int last=Score(num,y[idx_last]); 65 int next=Score(num,y[idx_next]); 66 if(last==1)W[num][s]--; 67 else if(last==-1)L[num][s]--; 68 if(next==1)W[num][s]++; 69 else if(next==-1)L[num][s]++; 70 idx_last=s;idx_next=(idx_next+n)%m; 71 } 72 } 73 } 74 ll answ=0,ansl=0; 75 for(int i=0;i<n;i++){ 76 answ+=w[x[i]][i%g]; 77 ansl+=l[x[i]][i%g]; 78 } 79 answ*=a;ansl*=a; 80 if(b){ 81 for(int i=0;i<n;i++){ 82 answ+=W[x[i]][i]; 83 ansl+=L[x[i]][i]; 84 } 85 } 86 int s=((ll)b*n)%m; 87 for(int i=0;i<c;i++){ 88 int s0=Score(x[i],y[(s+i)%m]); 89 if(s0==1)answ++; 90 else if(s0==-1)ansl++; 91 } 92 if(Is_exchange){ 93 // printf("%lld %lld\n",testl,testw); 94 printf("%lld %lld\n",ansl,answ); 95 }else{ 96 // printf("%lld %lld\n",testw,testl); 97 printf("%lld %lld\n",answ,ansl); 98 } 99 return 0; 100 }

51nod 1501 石頭剪刀布威力加強版