这次比赛归结起来就是:连蒙带猜,坑蒙拐骗,大胆猜测。
a.决战网球
组织字符串信息,维护当前局和当前场的两方胜负情况,注意换行符的输出。代码是比赛时着急写的,很丑。
#include<cstdio>
#include<iostream>
using namespace std;
int n;
char s[1005];
int a,b,c,d;
int notfirst;
int main()
{
//freopen("input.in","r",stdin);
scanf("%d",&n);
scanf("%s",s+1);
for(int i=1;i<=n;i++)
{
if(s[i]=='W')a++;
else b++;
if(a==4||b==4)
{
if(notfirst&&(c==0&&d==0))putchar('\n'); else notfirst=1;
printf("%d:%d\n",a,b);
if(a==4)c++; else if(b==4)d++;
a=0;b=0;
if(c==2||d==2){c=0;d=0;}
}
}
return 0;
}
b.ash
如果要枚举所有的两两组合,o(n^2)的时间必定会超时,但注意到每个元素只有不到100000,于是可以开一个100000的数组记录每个数字的出现次数,然后生成200000以内的所有平方数,对于每个平方数,枚举哪两个数加起来等于它,两个数的数量相乘就是组合个数,注意两个数相等时为c(n,2).
比赛时n*(n-1)/2被写成(n+(n-1))/2死活找不出错,居然这么大的错误过了91%的数据,不可思议!最后发现是sb错误,代码同样丑。
#include<cstdio>
#include<iostream>
using namespace std;
long long n,a[200005];
bool ok[200005];
long long sum;
int main()
{
// freopen("input.in","r",stdin);
scanf("%lld",&n);
int x;
for(int i=1;i<=n;i++){scanf("%d",&x);a[x]++;}
for(int i=1;i*i<=200000;i++)ok[i*i]=1;
for(int i=200000;i>0;i--)
{
if(!ok[i])continue;
for(int j=1;j<=i/2;j++)if(a[j])sum+=((long long)a[j]*a[i-j]);
if(i%2==0)sum+=((long long)a[i/2]*(a[i/2]-1))/2-(long long)a[i/2]*a[i/2];
}
printf("%lld\n",sum);
return 0;
}
c.欣姐姐的烦恼
lcm(a,b)=a*b/gcd(a,b),玄学瞎猜,交上去试一下居然过了,真是大跌眼镜。其实吧,如果n是奇数,则(n/2,n/2+1)的gcd应该是1,这时lcm最大,若n为偶数,从n/2向两边扩展,直到找到两个数的gcd为1,大概这样想:从n/2的两边应该很快就能找到这样的两个数gcd=1,如果在距离n/2更近的位置找到了两个数但他们的gcd不是1,至少是2,则这两种的a*b相差不大,但后一种除以2,影响是比较大的,所以选前一种,找到远点的gcd=1的。嗯,确实玄学,因为我智商低。
#include<cstdio>
#include<iostream>
using namespace std;
int n,t;
int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
int main()
{
//freopen("input.in","r",stdin);
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
if(n%2)
{
int m=n/2;
n=m+1;
while(gcd(m,n)!=1){m--;n++;}
printf("%lld\n",(long long)m*n);
}
else
{
int m=n/2;
n=m;
while(gcd(m,n)!=1){m--;n++;}
printf("%lld\n",(long long)m*n);
}
}
return 0;
}
d。Morse Code
一道水题。。因为这道没ak。。但好难思考。。最后还是不理解,ascll而非ascii,还有%大数而非128,为什么大家都能想到输出ascii字符呢?真的是奇怪。。这样的编码解码如果%大数后大于127,输出什么?这样明显不完备的编码有什么意义?wa了n次,没代码。。
e.给qz买五饭
n*k-sigma(ai)>ai并且k>max(ai),直接出结果。
#include<cstdio>
#include<iostream>
using namespace std;
int n;
int a[1005];
int main()
{
//freopen("input.in","r",stdin);
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
int maxn=0,sum=0;
for(int i=1;i<=n;i++)
{
if(a[i]>maxn)maxn=a[i];
sum+=a[i];
}
if((int)(2.0*sum/n+1)>maxn)maxn=(int)(2.0*sum/n+1);
printf("%d\n",maxn);
return 0;
}
f.gjc又研究数列了!大家快跑!!
一开始带着freopen交了上去wa了一发
#include<cstdio>
#include<iostream>
using namespace std;
int n;
int main()
{
//freopen("input.in","r",stdin);
while(scanf("%d",&n)!=EOF)
{
bool ok=0;
for(int i=30;i>=0;i--)if(n&(1<<i)){if(n-(1<<i)==0){ok=1;break;}}
if(ok)printf("Yes\n");else printf("No\n");
}
return 0;
}
g.狗哥买游戏
#include<cstdio>
#include<iostream>
using namespace std;
int n;
long long a,b;
int main()
{
//freopen("input.in","r",stdin);
scanf("%lld%lld",&a,&b);
printf("%lld\n",(10*a+b)/111%1111);
return 0;
}
h.神奇的手表
多计了多少时间与秒数无关,只须看时和分的关系即可。多的时间处理和答案输出还是有些东西的。
官方题解说把时分都换到秒里面,比较简单,感觉怪怪的。。反正只有自己的思路自己最接受。。
#include<cstdio>
#include<iostream>
using namespace std;
int d,h,m,s;
int main()
{
// freopen("input.in","r",stdin);
while(scanf("%d%d:%d:%d",&d,&h,&m,&s)!=EOF)
{
if(d==0&&h==0&&m==0&&s==0){printf("%d %02d:%02d:%02d\n",d,h,m,s);continue;}
int last=0;
last+=24*d;
if(m>h)last+=h+1;
else if(m<=h)last+=h;
s-=last;
while(s<0){m--;s+=60;}
while(m<0){m+=60;h--;}
if(h<0){d--;h+=24;}
printf("%d %02d:%02d:%02d\n",d,h,m,s);
}
return 0;
}
I: 这是一个NIm博弈裸题
前一两天刚做过2016新生杯初赛也有一道博弈的题,比这个简单,但那个基础思想很神奇,很启发,在我2016初赛那篇博文里有介绍。于是这道题我想:qz取两次,每次取完一堆,也可以只取一堆的一点儿,也就是说,qz每轮取0,1,2堆,而ksf每轮取0,1堆。
于是我就分类讨论了。n偶&&ksf先,ksf取0qz取2,ksf取1qz取1,qz必胜;
n偶&&qz先,qz先取2堆,转化为n偶&&ksf先,qz必胜;
n奇qz先,qz取1,转化为n偶ksf先,qz必胜。
n奇&&ksf先,ksf不管取0还是1都可以转化为qz必胜的情况。
不对啊。。怎么可能qz一定胜呢?有问题。想到1,1,1,1这种n偶ksf先的局面,因为每堆只有1个,所以qz每次限定死必须取2堆,ksf必须每次1堆,于是找到破绽了。
先看如果n堆每堆全为1:
qz先手:若n%3==1或2,qz胜,n%3==0,ksf胜
ksf先手:若n%3==0或2,qz胜,n%3==1,ksf胜
如果n堆仅有1堆数量非1:
qz先手:qz胜
ksf先手:n%3==2,qz胜,n%3==1或0,ksf胜
如果n堆仅有2堆数量非1:
qz先手:qz胜
ksf先手:qz胜
从2堆非1的大概有了些感觉,后面的应该qz必胜了。随便交上去试一试,!!!居然过了!
其实后面的一定可以向下转化,类似数学归纳法的思想。
#include<cstdio>
#include<iostream>
using namespace std;
int n,d,a[1000005];
bool ok;
int main()
{
scanf("%d%d",&n,&d);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
int sum=0;
for(int i=1;i<=n;i++)if(a[i]==1)sum++;
if(sum==n)
{
if(d==1&&n%3==0)ok=0;
else if(d==2&&n%3==1)ok=0;
else ok=1;
}
else if(sum==n-1)
{
if(d==1)ok=1;
else if(d==2&&n%3==2)ok=1;
else ok=0;
}
else ok=1;
if(ok)puts("Yes");
else puts("No");
return 0;
}
后来看官方题解,发现开始就讨论qz必输的情况,感觉有点难以想到。
j.只有你不存在的世界β
维护当前遇到的最高的高度,从左到右扫一遍,就好了。
#include<cstdio>
#include<iostream>
using namespace std;
int n,a[1000005],d[1000005],maxn,sum;
int main()
{
//freopen("input.in","r",stdin);
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
{
if(a[i]>maxn)
{
d[i]=a[i]-maxn;
maxn=a[i];
}
}
for(int i=1;i<=n;i++)sum+=d[i];
for(int i=1;i<=n;i++)
{
if(d[i])printf("%d %.5f\n",i,(double)d[i]/sum);
}
return 0;
}