南京理工大学第八届程序设计大赛count_prime

来源:互联网 发布:h3c路由器封端口 编辑:程序博客网 时间:2024/05/16 16:59

题目链接:https://icpc.njust.edu.cn/Contest/749/C

题目大意:在一个区间内找到与某个数互质的个数。

解题思路:容斥原理,去掉所有与它不互质的数即为所求。默比乌斯反演也能写,如果n能整除m,F(m)=b/m,否则F(m)=0。不过就显得有点笨重了,因为n和a,b都比较大,如果后台数据量大的话,我感觉会超时,好在这题两种方法能过。

容斥原理:

<span style="font-size:14px;">/* ********************************Author: danmuCreated Time: 2016年04月17日 星期日 21时50分29秒File Name: countPrime.cppVim Commandcopy -> yypaste -> p Pdel this line -> ddCtrl-Z -> u Ucopy into system -> "+y******************************** */#include <algorithm>#include <iostream>#include <cstdlib>#include <cstring>#include <iomanip>#include <string>#include <vector>#include <cstdio>#include <stack>#include <queue>#include <cmath>#include <list>#include <map>#include <set>#define ULL unsigned long long#define PI 3.1415926535#define INF 0x3f3f3f3f#define LL long long#define eps 1e-8using namespace std;bool isprime[100010];int prime[100010],tmpPrime[100010],tmpCnt,cnt;LL sum;void doprime(){cnt=0;isprime[0]=isprime[1]=false;memset(isprime,true,sizeof(isprime));for(int i=2;i<=100000;++i){if(isprime[i]){prime[cnt++]=i;for(LL j=(LL)i*i;j<=100000;j+=i)isprime[j]=false;}}}void dfs(int i,int nu,int x,int mu,LL b){//printf("%d %d %d %d %lld\n",i,nu,x,mu,b);if(nu==x){sum+=b/mu;return;}if(i==tmpCnt) return;dfs(i+1,nu+1,x,mu*tmpPrime[i],b);dfs(i+1,nu,x,mu,b);    }LL rong(LL x){LL s=0;for(int i=1;i<=tmpCnt;++i){sum=0;dfs(0,0,i,1,x);//printf("rong%d %lld\n",i,sum);if(i&1)s+=sum;elses-=sum;}//printf("%lld\n",s);return x-s;}int main(){//freopen("in.txt", "r", stdin);//freopen("out.txt", "w", stdout);int t;doprime();scanf("%d",&t);while(t--){LL a,b,n;tmpCnt=0;scanf("%lld%lld%lld",&a,&b,&n);for(int i=0;i<cnt&&(LL)prime[i]*prime[i]<=n;++i){if(n%prime[i]==0){tmpPrime[tmpCnt++]=prime[i];while(n%prime[i]==0) n/=prime[i];}}if(n>1) tmpPrime[tmpCnt++]=n;//printf("%lld\n",rong(b));printf("%lld\n",rong(b)-rong(a-1));}return 0;}</span>

莫比乌斯反演

/* ********************************Author: danmuCreated Time: 2016年04月19日 星期二 16时56分07秒File Name: countPrime1.cppVim Commandcopy -> yypaste -> p Pdel this line -> ddCtrl-Z -> u Ucopy into system -> "+y******************************** */#include <algorithm>#include <iostream>#include <cstdlib>#include <cstring>#include <iomanip>#include <string>#include <vector>#include <cstdio>#include <stack>#include <queue>#include <cmath>#include <list>#include <map>#include <set>#define ULL unsigned long long#define PI 3.1415926535#define INF 0x3f3f3f3f#define LL long long#define eps 1e-8#define MAX 100000using namespace std;bool vis[MAX+10];  int mu[MAX+10],prime[MAX+10],cnt;  void mobi(int n){      memset(vis,false,sizeof(vis));      mu[1]=1;      cnt=0;      for(int i=2;i<=n;++i){          if(!vis[i]){              prime[cnt++]=i;              mu[i]=-1;          }          for(int j=0;j<cnt&&i*prime[j]<=n;++j){              vis[i*prime[j]]=1;              if(i%prime[j]) mu[i*prime[j]]=-mu[i];              else{                  mu[i*prime[j]]=0;                  break;              }          }      }  }  int mobin(int n){      int m=1;      for(int i=2;i*i<=n;++i)          if(n%i==0){              m*=-1;              int k=0;              do{                  k++;                  if(k>1){                      m=0;                      break;                  }                  n/=i;              }while(n%i==0);          }      if(n>1) m*=-1;      return m;  }  int main(){//freopen("in.txt", "r", stdin);//freopen("out.txt", "w", stdout);int t;mobi(MAX);scanf("%d",&t);while(t--){LL a,b,n,ans1=0,ans2=0;scanf("%lld%lld%lld",&a,&b,&n);--a;for(int i=1;i<=sqrt(n*1.0)&&i<=a;++i){if(n%i==0){ans1+=mu[i]*(a/i);if(i!=n/i)ans1+=mobin(n/i)*(a/(n/i));}}for(int i=1;i<=sqrt(n*1.0)&&i<=b;++i){if(n%i==0){ans2+=mu[i]*(b/i);if(i!=n/i)ans2+=mobin(n/i)*(b/(n/i));}}printf("%lld\n",ans2-ans1);}return 0;}


0 0
原创粉丝点击