题目链接: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 : danmu Created Time : 2016年04月17日 星期日 21时50分29秒 File Name : countPrime.cpp Vim Command copy -> yy paste -> p P del this line -> dd Ctrl-Z -> u U copy 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 using 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; else s-=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 : danmu Created Time : 2016年04月19日 星期二 16时56分07秒 File Name : countPrime1.cpp Vim Command copy -> yy paste -> p P del this line -> dd Ctrl-Z -> u U copy 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 100000 using 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; }
南京理工大学第八届程序设计大赛count_prime
最新推荐文章于 2019-07-20 21:26:09 发布