这次网络赛开始先签了10题的到,然后依次做出来了3、7、11题。
开始的时候签到题两个队友先看到的,所以第10题是由两个队友开始时敲了出来一发过,同时我在看第7题;
然后AC的第3题三个人一起看的,AC的慢了的主要原因还是距离和点没转过来一开始……后来队友反应过来后这道题也就迎刃而解了(具体思路在下面);
第7题题目说的很花里胡哨,但题却异常简单,耽搁的时间太长是因为一开始我们理解成了回文字符串……
11题是我们做的最久、最慢的一道题,之后我个人死磕5题,队友磕2题,下面是按照解出的时间排序各个题的解题思路。
展开写写:
1010 Reports
题意:给你一串01组成的数字,如果其中存在相邻两个数相同(即…00…或者…11…)那就输出NO,不存在则输出YES。
思路:不需要思路直接写。
1003 Express Mail Taking
题意:有n个保险柜,编号为1-n,相邻编号的保险柜之间的距离为1,第k个保险柜用来打开其他保险柜(每次只能同时打开一个保险柜)。从1出发,需要从m个保险柜中取东西(取东西前先要去k柜输入密码)后再从1离开。问距离最短的路线长度。
思路:其实这道题……那个WA不该交,我们考虑到了最短路的求法:对于所有的柜子,如果m个柜子编号全部>k,那么每个柜子都要取完返回一次k柜,即2*abs(i-k),最后再加上起/终点往返k柜的距离(k-1)*2,若存在至少一个柜子编号<k,那么无论其他柜子编号如何,在上述得到的和中减去【最小】编号的一个i值柜和k柜之间的往返。
这个题说着丢脸,我们一开始卡出的原因竟然是没考虑到1-5之间的距离是4……
for(int i=0;i<m;i++){ int v; scanf("%d",&v); if(v<min)min=v; ans+=abs(k-v)*2; } ans+=k-1; if(min<=k){ ans-=(k-min)*2; }
1007 CCPC Training Class
题意:题面无比啰嗦,简而言之就是求给出的字符串中出现最多的字母出现的次数
思路:……我是怎么脑子锈了能联想到回文字符串的????
#include<bits/stdc++.h> using namespace std; #define LL long long int main() { int t; cin>>t; for(int kk=1;kk<=t;kk++) { string s; cin>>s; int l=s.size(); int a[28]; for(int i=0;i<=26;i++)a[i]=0; int flag=0; for(int i=0;i<l;i++) { a[s[i]-\'a\']++; } int ans=0; for(int i=0;i<=26;i++) { if(a[i]>ans)ans=a[i]; } // if(flag==1)ans++; printf("Case #%d: %d\n",kk,ans); } }
1011 3x3 Convolution
题意:给出n*n矩阵A和3*3矩阵K(n>=3), 定义n*n矩阵C(A,K),它的每一项Cx,y满足
定义Cm(A,K)=C(Cm−1(A,K),K) and C1(A,K)=C(A,K),求limt→∞Ct(A,K)。
思路:这题解题主力是两个队友。
样例中答案只有两种,原矩阵和零矩阵,经过一番写作理智读作胡乱的分析,当输入的K矩阵只有左上角有不为0的数,其他位置都是0时,输出原矩阵;其他情况输出零矩阵。
补充:C1,1=A1,1*K1,1+A1,2*K1,2+......+A3,2*K3,2+A3,3*K3,3
......
Cn,n-1=An,n-1*K1,1+An,n*K1,2
Cn,n=An,n*K1,1
(1)if K1,1==0,Cn,n就为0;接下来的C2中的Cn,n-1也会变成0,以此类推,最后矩阵Ct会变成零矩阵。
(2)if K1,1!=0,K其他位都为0,那么矩阵中的所有项相当于乘上了K1,1的t次方,各项之间的比值不变,于是答案是原矩阵。
(3)if K1,1!=0,K其他位中存在不为0的项,因为K1,1<1,Cn,n会不断变小,直至无限趋近于0
推理可得,Ct中的Cn,n-1=An,n-1*Kt1,1+t*An,n*Kt-11,1*K1,2,
由于K所有项之和为1,K1,1与K1,2都小于1,分析可得当t→∞时,Ct中的该项趋近于0;
同理,其他项在Ct中也都趋近于0,于是最后得到的Ct是零矩阵。
然而交的时候,我们还PE了一发,矩阵最后一位后是没有空格的enmmm
#include<bits/stdc++.h> using namespace std; #define LL long long int a[55][55]; int v[5][5]; int c[50][50]; int main() { int t; cin>>t; while(t--) { int n; cin>>n; for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { scanf("%d",&a[i][j]); } } LL sum=0; for(int i=1;i<=3;i++) { for(int j=1;j<=3;j++) { scanf("%d",&v[i][j]); if(v[i][j]!=0)sum++; } } if(sum==1) { for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { printf("%d ",a[i][j]); } printf("\n"); } } else { for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { printf("0 "); } printf("\n"); } } } }
if(j==n) printf("0"); else printf("0 ");
1005 Lunch
题意:有n个数,两人轮流进行操作,每次操作能将其中一个数x变为k*(x/k),此处的k必须是x的因子且k!=x。当场上的数均为1时游戏结束,当前操作方输。问先手可不可以获胜。
思路:这道题观察发现,对于一个数,分成偶数个会增加偶数个操作,于是这样不会使得最后的胜负情况发生改变;分成奇数个则刚好相反,会改变最后的胜负情况。
把数x分解,x就变成了一堆【质因子】的乘积。
因此我们把将这个数的所有质因子当作一堆石子的个数。
2是一个特殊的数字,因为它还是偶数,所以我们不管分几次取2,都相当于直接把2全取走。但是又必须要取走2,所以就把所有的因数2当作一个石子一起取走。
然后就变成了nim博弈,即:有n堆石子,两人轮流进行操作,每次可从任意一堆石子里取走任意多枚石子,不能不取,问先手必胜还是必败。
对于答案,求每一堆的石子数的异或和,若为0则必败,否则必胜。
至此终于转化成了我们熟悉的博弈!虽然当时还是没做出来orz
这次比赛前我还在AcWing算法群里看了一道nim博弈题,但是临了要用了却一点都没转过来脑子,我是我们队最大的、打了比赛最久的一个,这次我们队这道题比赛失利主要责任在我。说到底,也是我们平时博弈练习的少了,这一方面需要重点抓一下。 接下来我们想要取得更好的成绩的话需要进行针对性训练了,个人需要着重练一下博弈题,这次5题如果之前多练一下的话不该错失的。
#include <bits/stdc++.h> using namespace std; const int N=1e5+10; int prime[N],k; bool isprime[N]; void Prime(){ fill(isprime,isprime+N,1); k=0; for(int i=2;i<=N;i++) { if(isprime[i]) prime[k++]=i; for(int j=0;j<k;j++) { if(i*prime[j]>N) break; isprime[i*prime[j]]=0; if(i%prime[j]==0) break; } } } int main() { int n,t,a[15]; Prime(); scanf("%d",&t); while(t--){ scanf("%d",&n); int ans=0; for(int i=1;i<=n;i++){ scanf("%d",&a[i]); int flag=((a[i]%2)^1); while(a[i]%2==0) a[i]/=2; int sum=0; for(int j=0;j<k&&prime[j]*prime[j]<=a[i];j++){ while(a[i]%prime[j]==0){ sum++; a[i]/=prime[j]; } } if(a[i]>1) sum++; ans^=(sum+flag); } if(ans) printf("W\n"); else printf("L\n"); } return 0; }