题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5391
题目大意:一个球初始体积为1,一天天变大,第一天变大1倍,第二天变大2倍,第n天变大n倍。问当第 n-1天的时候,体积变为多少。注意答案对n取模。
思路:题目意思搞了好久,其实就是第一天是1,第二天是1*2,第三天是1*2*3,也就是当第n天的时候是n!。那么答案就是(n-1)! % n。
题目里面n是10^9,不可能直接弄阶乘。这时可以想想,能不能找找规律看。
打表以后发现,如果是素数,答案就是n-1,否则就是0。当然这里4是个例外。
于是问题就转化成为求n是否为素数。求素数那么再简单不过了。最朴素的方法:对于一个素数n,看他的2~sqrt(n)范围里面,能不能被他整除。
注意这个程序,我刚开始用__int64定义变量,结果是TLE。因为碰到过这种情况,报着试一试的心态改为int,就AC了,跑了900多ms。
#include<stdio.h> #include<string.h> #include<math.h> #define LL __int64 int main() { int T; int i,j,n,k; scanf("%d",&T); int flag=0; while(T--) { flag=0; scanf("%d",&n); k=sqrt(n); for(i=2;i<=k;i++) { if(n%i==0){ flag=1;break; } } if(n==4){ printf("2\n");continue; } if(flag)printf("0\n"); else printf("%d\n",n-1); } return 0; }
其实刚开始的时候,一直想着筛出素数来做。后来就用线性素数筛法写了一次。但是效果不好,也要800ms。
#include<stdio.h> #include<string.h> #include<math.h> #define Max 40005 int prime[40005]; bool isprime[40005]; int tot=0; void sushu() //线性素数筛法 { memset(isprime,true,sizeof(isprime)); memset(prime,0,sizeof(prime)); isprime[0]=false; isprime[1]=false; for(int i=2;i<=Max;i++) { if(isprime[i]){ prime[tot++]=i; } for(int j=i;j<=tot&&i*prime[j]<=Max;j++) { isprime[i*prime[j]]=false; if(!(i%prime[j]))break; } } } int main() { sushu(); int T,n,k,i,j,flag; scanf("%d",&T); while(T--) { flag=0; scanf("%d",&n); if(n==4){ printf("2\n");continue; } k=sqrt(n); for(i=0;prime[i]<=k;i++) //还是利用最朴素的判断一个数是否为素数的方法,但是有优化:在2-k里面,只要被其中的素数整除,就认为他不是素数了。这里就 //通过预处理出来的素数,把中间的合数筛去了。 { if(n%prime[i]==0){ flag=1;break; } } if(flag==0)printf("%d\n",n-1); else printf("0\n"); } return 0; }
其实呢,在想着用处理素数的方法判断素数的时候,以为会有很大的效果,但是却不是这样,真的是很失望。后来我找到了别人的一份200 ms的代码。思路基本一致,就是素数筛的方法有点差异。那就膜拜一下。
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; #define mod 258280327 #define ll long long int prime[100000]={2}; int cnt; bool is_prime(int k){ for(int i=0;prime[i]*prime[i]<=k;i++){ if(k%prime[i]==0)return false; } return true; } int main(){ int t,n; cnt=1; for(int i=3;i<100000;i++){ if(is_prime(i)){ prime[cnt++]=i; } } for(int i=1;i<=100;i++) printf("%d ",prime[i]); //for(int i=0;i<30;i++)cout<<prime[i]<<endl; scanf("%d",&t); while(t--){ scanf("%d",&n); if(n==4){ printf("%d\n",2); } else if(is_prime(n)){ printf("%d\n",n-1); } else printf("0\n"); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
hdu5391 Zball in Tina Town(素数筛法)
原文地址:http://blog.csdn.net/aaaaacmer/article/details/47701359