纪中游记(一)
2019.08.01
昨晚听说台风过境,不过并无大碍。但我还是想吐槽一句:中山的雨来的真猛。
写在前面的一句话
第一次打下来一个大模拟,虽然可能会爆0,但是这种全身心投入做题的感觉真的很爽!
下午看了成绩,还可以,总算没有爆零。
机房大佬的游记
T0(游戏)
初
我一看到题目中的“必胜”,就知道这道题一定是博弈论,放弃(现在亏死了)
复
用f[i][j]表示从(1,1)到(i,j)的矩阵先手的胜负情况,那么就有:
if(f[ii-1][jj]==0&&(q[ii][jj]-q[ii-1][jj])%2==0) { f[ii][jj]=1; } else if(f[ii][jj-1]==0&&(q[ii][jj]-q[ii][jj-1])%2==0) { f[ii][jj]=1;
}
如果上一步先手为负,且这一步可以选,就可以转移为胜。
终
很简单的一道递推。
1 #include<bits/stdc++.h> 2 using namespace std; 3 long long q[1005][1005]; 4 bool f[1005][1005]; 5 int main() 6 { 7 int T; 8 scanf("%d",&T); 9 for(int i=1;i<=T;i++) 10 { 11 memset(q,0,sizeof(q)); 12 memset(f,0,sizeof(f)); 13 int N; 14 scanf("%d",&N); 15 for(int j=1;j<=N;j++) 16 { 17 for(int k=1;k<=N;k++) 18 { 19 long long op; 20 scanf("%lld",&q[j][k]); 21 q[j][k]+=q[j-1][k]+q[j][k-1]-q[j-1][k-1]; 22 } 23 } 24 25 for(int ii=1;ii<=N;ii++) 26 { 27 for(int jj=1;jj<=N;jj++) 28 { 29 if(f[ii-1][jj]==0&&(q[ii][jj]-q[ii-1][jj])%2==0) 30 { 31 f[ii][jj]=1; 32 } 33 else if(f[ii][jj-1]==0&&(q[ii][jj]-q[ii][jj-1])%2==0) 34 { 35 f[ii][jj]=1; 36 37 } 38 } 39 } 40 cout<<(f[N][N]?"W":"L")<<endl; 41 } 42 return 0; 43 }
T1(六边形)
初
这道题我按模拟做的,码了1.5h,首先预处理,直接把1~10000算出来,结果蜜汁45.5分。
复
写这道题付出了很大心力,我不甘心,调了一个下午,终于放弃。
不过,在调试的时候,我发现了很多由于粗心而犯的错误,还算是有所收获。
终
我会AC的!
1 #include<bits/stdc++.h> 2 using namespace std; 3 int a[10005],num[100],tot=2,sum[6],ki=7,k=0; 4 int main() 5 { 6 a[1]=1; a[2]=2; a[3]=3; a[4]=4; a[5]=5; a[6]=2; a[7]=3; a[8]=1; a[9]=4; 7 sum[1]=2; sum[2]=2; sum[3]=2; sum[4]=2; sum[5]=1; 8 num[1]=7; 9 for(int i=2;i<=60;i++) 10 { 11 num[i]=num[i-1]+6*i; 12 } 13 for(int i=10;i<=10000;i++) 14 { 15 int minn=0x3f3f3f3f; 16 if(i==num[tot]){ 17 ki++; 18 for(int j=5;j>=1;j--){ 19 if(j==a[i-1]) continue; 20 if(j==a[num[tot-1]+1]) continue; 21 if(j==a[i-ki]) continue; 22 if(sum[j]<=minn){ 23 minn=sum[j]; a[i]=j; 24 } 25 } 26 sum[a[i]]++; 27 continue; 28 } 29 if(i==num[tot]+1){ 30 for(int j=5;j>=1;j--){ 31 if(j==a[i-1]) continue; 32 if(j==a[i-ki]) continue; 33 if(sum[j]<=minn){ 34 minn=sum[j]; a[i]=j; k=1; 35 } 36 } 37 sum[a[i]]++; 38 tot++; 39 continue; 40 } 41 k++; 42 if(k==tot){ 43 ki++; 44 k=0; 45 for(int j=5;j>=1;j--){ 46 if(j==a[i-1]) continue; 47 if(j==a[i-ki]) continue; 48 if(sum[j]<=minn){ 49 minn=sum[j]; a[i]=j; 50 } 51 } 52 sum[a[i]]++; 53 continue; 54 } 55 for(int j=5;j>=1;j--){ 56 if(j==a[i-1]) continue; 57 if(j==a[i-ki]) continue; 58 if(j==a[i-ki-1]) continue; 59 if(sum[j]<=minn){ 60 minn=sum[j]; a[i]=j; 61 } 62 } 63 sum[a[i]]++; 64 } 65 //cout<<sum[1]<<" "<<sum[2]<<" "<<sum[3]<<" "<<sum[4]<<' '<<sum[5]<<endl; 66 int T,n; 67 scanf("%d",&T); 68 while(T--){ 69 scanf("%d",&n); 70 71 printf("%d\n",a[n]); 72 } 73 return 0; 74 }
T2(数列)
初
我原以为这道题是区间DP,于是打了个板子,测了下样例,就跑去做T1了。
复
经过ZX大佬的讲解,我发现这道题炒鸡简单,用前缀和之差表示子序列,为防止超限顺便mod k,接着再用一个桶计算方案数,其余看代码自然明晰。
1 #include<bits/stdc++.h> 2 #define lll long long 3 using namespace std; 4 int T; 5 int t[1000005]; 6 int main() 7 { 8 scanf("%d",&T); 9 for(int i=1;i<=T;i++) 10 { 11 lll ans=0; 12 memset(t,0,sizeof(t)); 13 int k,n; 14 scanf("%d %d",&k,&n); 15 int op,qian=0; 16 t[0]++; 17 for(int i=1;i<=n;i++) 18 { 19 scanf("%d",&op); 20 qian=(qian+op)%k; 21 t[qian]++; 22 } 23 for(int i=0;i<k;i++) 24 { 25 if(t[i]) 26 ans+=(t[i]-1+1)*(t[i]-1)/2; 27 } 28 printf("%lld",ans); 29 cout<<endl; 30 } 31 return 0; 32 }
终
为什么简单的题却不会做呢?