NOIP水题大竞赛

2015-11-03 13:00:00 ~ 2015-11-03 22:00:00

本次比赛都是小编收集来的水题,意在为大家的NOIP竞赛打气。欢迎大神们与菜鸟们前来虐场! 邀请码:7b6c

/ 不好意思,T2数据的确出错了。给大家带来不便,请多包涵啦。。(现已改正)/ //T1的题面改一下:不超过X改为小于X

本次比赛是本蒟蒻第一次办比赛。给大家带来不少麻烦,敬请谅解!

T1: 本题可采用队列思想。首先将0放入队列中,接下来不断从队列中取出一个超级质数(或者是0)在其末尾添加0到9的数字后判断新数是否为超级质数,是就入队。最后在所有入过队的数中,输出X以内的数。还可以保证输出是有序的。

include <cstdio>

include <cmath>

include <iostream>

include <cstdlib>

using namespace std;

int q[100],head=0,tail=1,cnt;

int isprime(int x) { if(x<2) return 0; int i; for(i=2;i*i<=x;i++) { if(x%i==0) return 0; } return 1; }

int main() { int a,i,x; scanf("%d\n",&x); q[head]=0; while(head<tail) { a=q[head]; if(a>100000000) break; for(int i=1;i<=9;i++) { if(isprime(a10+i)) { q[tail++]=a10+i; } } head++; } for(i=1;i<tail;i++) { if(q[i]<x) cnt++; } printf("%d\n",cnt); for(i=1;i<=cnt;i++) { printf("%d\n",q[i]); } return 0; }

T2: 这题很不好意思,开始时数据错了,原因就是数组下标为0是没有考虑。 其他就是一些细节问题。

include <cstdio>

include <iostream>

using namespace std;

int year,month,day,days;

int sum_day(int month,int day)//计算日期 { int day_tab[13]={0,31,28,31,30,31,30,31,31,30,31,30,31}; int i; for(i=1;i<month;i++)//累加所在日之前的天数 { day+=day_tab[i]; } return day; }

int leap(int year)//判断是否为闰年 { int tmp; tmp=year%4==0&&year%100!=0||year%400==0; return tmp; }

int main() { scanf("%d %d %d\n",&year,&month,&day); days=sum_day(month,day); if(leap(year)&&month>=3) days++; printf("%d\n",days); return 0; }

T3: 对于这道题,一个很简单的想法就是寻找每一种情况。我们只要穷举每块牧草的边长,通过检验四块牧草的面积之和是否等于N来判断是否合法,最后统计合法方案的个数。注意任何时候牧草的面积都不能超过N,这就给我们一个很有用的约束条件。我们可以写出一个很简单的四重循环解决问题: for (i=0;ii<=n;i++) for (j=0;ii+jj<=n;j++) for (k=0; ii+jj+kk<=n;k++) for (l=0; ii+jj+kk+ll<=n;l++) if (ii+jj+kk+ll==n) ans++; 不过为了让程序运行得更快,我们可以加一个小优化:如果我们已经知道了前三块牧草的面积,我们可以立即知道最后一块牧草的面积,只要判断它是否为完全平方数即可,于是就省去一重循环。

PS:其实网上也有DP的做法,在这里不再赘述。

include <cstdio>

include <cstring>

include <iostream>

using namespace std;

int n,ans=0; int f[10010]/用于判断完全平方数/;

int main() { scanf("%d\n",&n); memset(f,0,sizeof(f)); for(int i=0;ii<=n;i++) { f[ii]=1;//先找出所有完全平方数 } for(int i=0;ii<=n;i++) { for(int j=0;ii+jj<=n;j++) { for(int k=0;ii+jj+kk<=n;k++) { if(f[n-ii-jj-k*k]) ans++; } } } printf("%d\n",ans); return 0; }

T4: 魔方阵中各数的排列是规律的。在这里仅提供一种方法。具体如下: 1.将1放在第一行中间一列。 2.从第二行开始直到nn止各数依次按下列规则存放:每一个数存放的行比前一个数的行数减1,列数加1(如33魔方阵中5在4的上一行后一列)。 3.如果上一个数的行数为1,则下一个数的行数为n(指最后一行)。如:1在第一行,则2应该放在最后一行,同时列数加1. 4.当上一个数的列数为n时,下一个数的列数应为1,并且行数减1.如2在第3行最后一列,则3应该放在第2行第1列。 5.如果按以上规则确定的位置上已有数,或者上一个数是第1行第n列时,则把下一个数放在上一个数的下面。如:按以上规则,4应该放在第1行第2列,但此时该位置已有数字1,所以4就放在3的下面。 按以上方法就可以得到奇数阶的魔方阵。

————以上仅为多种方法中的一种。如果各位大神还有不同方法,欢迎与小编一起交流! PS:关于Special Judge 的问题,详情请咨询管理员。

include <cstdio>

include <iostream>

using namespace std;

int a[1010][1010];

int main() { int i,j,k,n; scanf("%d\n",&n); for(i=1;i<=n;i++)//初始化 { for(j=1;j<=n;j++) { a[i][j]=0; } } //建立魔方阵 j=n/2+1; a[1][j]=1; for(k=2;k<=n*n;k++) { i--; j++; if(i<1&&j>n) { i+=2; j--; } else { if(i<1) i=n; if(j>n) j=1; } if(!a[i][j]) { a[i][j]=k; } else { i+=2; j--; a[i][j]=k; } } for(i=1;i<=n;i++) { for(j=1;j<=n;j++) { printf("%d ",a[i][j]); } printf("\n"); } return 0; }

T5: 没来得及写题解,不过这道题就是裸递推。设f[i]为圆上有i2个点的方案数,则不难推出: f[n]=f[0]f[n-1]+f[1]f[n-2]+......f[n-1]f0 数组f即为著名的Catalan数列,有兴趣的大神可以自己研究,这里不再介绍。

include <cstdio>

include <iostream>

using namespace std;

long long f[31]; int k;

int main() { int i,j; scanf("%d\n",&k); f[0]=f[1]=1; for(i=2;i<=k;i++) { for(j=0;j<i;j++) { f[i]+=(f[j]*f[i-j-1]); } } printf("%lld ",f[k]); printf("%d\n",k+1); return 0; }