南京理工大学第八届程序设计大赛 #C Count_Prime Solution

来源:互联网 发布:.uno域名 编辑:程序博客网 时间:2024/06/05 07:14

Description
给定你一个数n,请你统计出在[a,b]这个区间中和n互质的数的个数。
两个数互质当且仅当他们除了1之外没有其他的公共因子或者他们最大的公共因子是1。1和任何数是互素的。 Input 第一行输入一个整数T(1 <= T <= 100),表示T组测试数据。 接下来T行,每行3个整数a,b,n(1 <= a <=b <=10^15, 1<= n <= 10^9),用空格隔开。 Output 输出一个整数表示和n互质的数的个数。
Sample Input

2
1 10 2
3 10 5

Sample Output

5 6

感觉自己讲不清楚,引用一下NJUST comzyh的题解吧,总而言之就是分解+容斥原理

容斥原理、先对n分解质因数,分别记录每个质因数,那么所求区间内与某个质因数不互质的个数就是n/r(i),假设r(i)是r的某个质因子 假设只有三个质因子,总的不互质的个数应该为p1+p2+p3-p1p2-p1p3-p2p3+p1p2*p3, 及容斥原理,pi代表n/r(i),即与某个质因子不互质的数的个数,当有更多个质因子的时候,可以用状态压缩解决,二进制位上是1表示这个质因子被取进去了。如果有奇数个1就相加,反之则相减。

C++ Code#include <stdio.h>#include <math.h>#include <iostream>#include <bitset>using namespace std;const int inf=0x3f3f3f3f;const double pi= acos(-1.0);const double esp=1e-6;const int MAX=2*1e5+10;long long prime[MAX];long long sprime[MAX];bitset<MAX> pri;long long k,cnt;void is_prime() {    pri.set();    for(long long i=2; i<MAX; i++) {        if(pri[i]) {            prime[k++]=i;            for(long long j=i+i; j<MAX; j+=i)                pri[j]=0;        }    }}void Divide(long long n) {    cnt=0;    long long t=(long long)sqrt(1.0*n);    for(long long i=0; prime[i]<=t; i++) {        if(n%prime[i]==0) {            sprime[cnt++]=prime[i];            while(n%prime[i]==0)                n/=prime[i];        }    }    if(n>1)        sprime[cnt++]=n;}long long Ex(long long n) {    long long q[MAX];    long long sum=0;    long long t=1;    q[0]=-1;    for(long long i=0; i<cnt; i++) {        long long x=t;        for(long long j=0; j<x; j++) {            q[t]=q[j]*sprime[i]*(-1);            t++;        }    }    for(long long i=1; i<t; i++)        sum+=n/q[i];    return sum;}int main() {    int T;    int icase=1;    long long A,B,N;    long long res;    is_prime();    cin>>T;    while(T--) {        cin>>A>>B>>N;        Divide(N);        res=(B-Ex(B))-(A-1-Ex(A-1));        cout<<res<<endl;    }    return 0;}
0 0
原创粉丝点击