hdu5391 Zball in Tina Town(素数筛法)

17 篇文章 0 订阅

题目链接: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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值