【纪中受难记】——Day1:没有爆零
上午考完感觉心情一般般,第二题貌似可以打表但是没打,自认为是“简单的模拟题”,其他题没动。
下午出来:0/36.4/0,十分心痛。
果然,菜就是原罪。
1.游戏
|
这就是一道简单的递推。
首先分析一下状态,我们用增加一行/一列的方法考虑。
1.最开始的状态是由一个数组成的,要么是奇数要么是偶数,因为只能拿偶数,所以偶即赢,奇即输,分别用1(先手必赢)和0(先手必输)表示。
2.不断扩充状态,我们发现只要考虑增加的一行或者一列的和为奇还是偶,用前缀和来表示,如果为奇,则不考虑这行/列。
之后会出现几种情况:
1|0,1|1,0|0,1|-,0|-,0|0(|号表示分隔行和列)
发现两边都有的情况下只要取!(a&b)即可,只有一边则取该边的异或。
3.列递推式即可解决。
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 using namespace std; 5 const int N=1e3+10; 6 int t,sumh[N][N],sums[N][N],a[N][N],state[N][N]; 7 int n; 8 int main(){ 9 scanf("%d",&t); 10 for(int q=1;q<=t;q++){ 11 memset(sumh,0,sizeof(sumh)); 12 memset(sums,0,sizeof(sums)); 13 memset(a,0,sizeof(a)); 14 memset(state,0,sizeof(state)); 15 scanf("%d",&n); 16 for(int i=1;i<=n;i++){ 17 for(int j=1;j<=n;j++){ 18 scanf("%d",&a[i][j]); 19 sumh[i][j]=sumh[i][j-1]+a[i][j]; 20 sums[i][j]=sums[i-1][j]+a[i][j]; 21 } 22 } 23 state[1][1]=a[1][1]%2==0?1:0; 24 for(int i=1;i<=n;i++){ 25 for(int j=1;j<=n;j++){ 26 int sh=sumh[i][j]%2==0?0:1; 27 int ss=sums[i][j]%2==0?0:1; 28 if(sh&&ss) state[i][j]=0; 29 else if(sh&&!ss) state[i][j]=state[i][j-1]^1; 30 else if(!sh&&ss) state[i][j]=state[i-1][j]^1; 31 else state[i][j]=!(state[i-1][j]&state[i][j-1]); 32 } 33 } 34 if(state[n][n]==1) cout<<"W"<<endl; 35 else cout<<"L"<<endl; 36 } 37 return 0; 38 // for(int i=1;i<=n;i++){ 39 // for(int j=1;j<=n;j++){ 40 // printf("%d ",a[i][j]); 41 // } 42 // cout<<endl; 43 // } 44 // for(int i=1;i<=n;i++){ 45 // for(int j=1;j<=n;j++){ 46 // printf("%d ",sumh[i][j]); 47 // } 48 // cout<<endl; 49 // }for(int i=1;i<=n;i++){ 50 // for(int j=1;j<=n;j++){ 51 // printf("%d ",sums[i][j]); 52 // } 53 // cout<<endl; 54 // } 55 }
2.六边形
|
这是坑到我的“简单的模拟”。
1.找出一个点i需要与之判断的相邻点:
(1)点i-1
(2)内圈的一个或两个点。
(3)如果是每圈的最后一个点,则要与每圈的第一个点判断。
(4)如果是每圈的第一个点,则要与上一圈的第一点和最后一个点判断。(这点很重要)
2.模拟,也可以打表解决。
错误范例:
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 using namespace std; 5 typedef long long ll; 6 const ll N=1e5+10; 7 ll n,a[N],six[N],ang[N],change[N],cag[N],q[6]; 8 ll cen(ll x){ 9 return (x-1)/6; 10 } 11 void init(){ 12 six[1]=6,ang[1]=1,cag[1]=1;change[1]=0; 13 for(ll i=2;i<=11000;i++){ 14 six[i]=i*6; 15 ang[i]=ang[i-1]+six[i-1]; 16 if(ang[i]<=11000) cag[ang[i]]=i; 17 } 18 for(ll i=1,j=1;i<=11000;i++){ 19 if(!cag[i]) cag[i]=j; 20 else cag[i]=j++; 21 } 22 for(ll i=1;ang[i]<=11000;i++){//ang1=1,ang2=7,ang3=19(ch1=0,ch7=6,ch19=12) 23 change[ang[i]]=six[cag[ang[i]]-1]; 24 for(ll j=1;j<=5;j++){ 25 change[ang[i]+j*cag[ang[i]]]=change[ang[i]]+j; 26 } 27 } 28 } 29 ll fch(ll x){ 30 while(change[x])x++; 31 return change[x]; 32 } 33 int main(){ 34 // freopen("in.txt","r",stdin); 35 init(); 36 scanf("%lld",&n); 37 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,a[10]=5,a[11]=1,a[12]=2,a[13]=3,a[14]=1; 38 q[1]=4,q[2]=3,q[3]=3,q[4]=2,q[5]=2; 39 for(ll i=15;i<=11000;i++){ 40 ll minn=1000000,minnum=0; 41 ll judge[6]; 42 memset(judge,0,sizeof(judge)); 43 judge[a[i-1]]=1; 44 if(change[i]){ 45 judge[a[i-change[i]]]=1; 46 if(change[i]%6==0) judge[a[i-change[i]+1]]=1; 47 } 48 else if(change[i-1]&&change[i-1]%6==0){ 49 judge[a[i-1]]=1; 50 judge[a[i-change[i-1]+1]]=1; 51 } 52 else{ 53 judge[a[i-fch(i)]]=1; 54 judge[a[i-fch(i)+1]]=1; 55 } 56 for(ll j=1;j<=5;j++){ 57 if(judge[j]) continue; 58 if(q[j]<minn){ 59 minn=q[j]; 60 minnum=j; 61 } 62 } 63 a[i]=minnum; 64 q[minnum]++; 65 // if(i==100){ 66 // for(int i=1;i<=5;i++) cout<<judge[i]<<" "; 67 // cout<<endl; 68 // cout<<ang[i]<<" "<<minnum<<" "<<minn<<" "<<fch(i)<<" "<<change[i]<<endl; 69 // } 70 } 71 for(ll i=1,wer;i<=n;i++){ 72 scanf("%lld",&wer); 73 printf("%lld\n",a[wer]); 74 } 75 // for(ll i=1;i<=100;i++) cout<<six[i]<<" "; 76 // cout<<endl; 77 // for(ll i=1;i<=100;i++) cout<<ang[i]<<" "; 78 // cout<<endl; 79 // for(ll i=1;i<=100;i++) cout<<cag[i]<<" "; 80 // cout<<endl; 81 // for(ll i=1;i<=100;i++) cout<<i<<" "<<change[i]<<endl; 82 // cout<<endl; 83 return 0; 84 }
找空改吧。
3.数列
|
这道题目有两种解法:
解法1:前缀和同余:
一段骚操作之后,我们将前缀和处理出来,按照从小到大排个序;
然后我们数相同的数字,因为在原排列中,任取两个相同数字间的一段都是k的倍数,所以这样的段共有 个。
所以,数数字就行了(笑)。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 using namespace std; 6 typedef long long ll; 7 const ll N=5e5+10; 8 ll t,k,n,a[N],ans; 9 ll c(ll m,ll n){ 10 ll ans=1; 11 for(ll i=m,j=1;j<=n;j++,i--) ans*=i; 12 for(ll i=1;i<=n;i++) ans/=i; 13 return ans; 14 } 15 int main(){ 16 scanf("%lld",&t); 17 for(ll q=1;q<=t;q++){ 18 memset(a,0,sizeof(a)); 19 ans=0; 20 scanf("%lld%lld",&k,&n); 21 ll p; 22 for(ll i=1;i<=n;i++){ 23 scanf("%lld",&p); 24 a[i]=(a[i-1]+p)%k; 25 } 26 sort(a+1,a+n+1); 27 ll s=1; 28 for(ll i=1;i<=n;i++){ 29 if(a[i]==a[i-1]) s++; 30 else{ 31 ans+=c(s,2); 32 s=1; 33 } 34 } 35 ans+=c(s,2); 36 printf("%lld\n",ans); 37 } 38 return 0; 39 }
解法2:分治:
一分为二,处理过中间线的部分即可。
总结:
第一天过得很充实,虽然分数不高,但捡了很多忘掉的知识,所以明天继续加油啦!
(qwq我想看mea直播)