质因子和容斥原理

算一个数字m,1~n之间有多少个与n互质的数

把n的素因子提取,进行二进制枚举,容斥

模板如下

 1 il void pan(ll k){
 2     cnt=0;
 3     ll kk=sqrt(k);
 4     for(ll i=2;i<=kk;i++){
 5         if(k%i==0){
 6             s[cnt++]=i;
 7             while(k%i==0){k/=i;}
 8         }
 9     }
10     if(k!=1){
11         s[cnt++]=k;
12     }
13     return;
14 }
15 ll all(ll k){
16     ll ans=0;
17     for(ll i=1;i<((ll)1<<cnt);i++){
18         ll sum=1,num1=0,tmp;
19         for(ll j=0;j<cnt;j++){
20             if(i&((ll)1<<j)){
21                 sum*=s[j];num1++;
22             }
23         }
24         tmp=k/sum;
25         if(num1&1){ans+=tmp;}
26         else{
27             ans-=tmp;
28         }
29     }
30     return k-ans;
31 }
View Code

hdu4135

题意:输入n,m,k,在区间n~m中有多少跟k互质的数

思路:就是模板。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 #define il inline
 5 #define it register int
 6 #define lowbit(x) (x)&(-x)
 7 #define mem(a,b) memset(a,b,sizeof(a))
 8 #define mod 1000000007
 9 const int maxn=1e5+10;
10 ll n,m,k2;
11 int t;
12 int cnt;
13 ll s[100];
14 il void pan(ll k){
15     cnt=0;
16     ll kk=sqrt(k);
17     for(ll i=2;i<=kk;i++){
18         if(k%i==0){
19             s[cnt++]=i;
20             while(k%i==0){k/=i;}
21         }
22     }
23     if(k!=1){
24         s[cnt++]=k;
25     }
26     return;
27 }
28 ll all(ll k){
29     ll ans=0;
30     for(ll i=1;i<((ll)1<<cnt);i++){
31         ll sum=1,num1=0,tmp=i;
32         for(ll j=0;j<cnt;j++){
33             if(i&((ll)1<<j)){
34                 sum*=s[j];num1++;
35             }
36         }
37         tmp=k/sum;
38         if(num1&1){ans+=tmp;}
39         else{
40             ans-=tmp;
41         }
42     }
43     return k-ans;
44 }
45 int main(){
46     it cc=1;
47     scanf("%d",&t);
48     while(t--){
49         scanf("%lld%lld%lld",&n,&m,&k2);
50         pan(k2);//cout<<all(2)<<endl;
51         printf("Case #%d: %lld\n",cc++,all(m)-all(n-(ll)1));
52     }
53     return 0;
54 }
View Code

cf一道D题

题意:输入n,m,gcd(n,m)=gcd(n+x,m)的x有多少个,x的范围是0~m-1

思路:k=gcd(n,m),n=k*a1,m=k*a2,n+x=k*a3

a1,a2,a3必定互质

就是求n~n+m-1之中有多少跟n/k互质的数

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 #define il inline
 5 #define it register int
 6 #define lowbit(x) (x)&(-x)
 7 #define mem(a,b) memset(a,b,sizeof(a))
 8 #define mod 1000000007
 9 const int maxn=1e5+10;
10 ll n,m;
11 int t;
12 int cnt;
13 ll s[100];
14 il void pan(ll k){
15     cnt=0;
16     ll kk=sqrt(k);
17     for(ll i=2;i<=kk;i++){
18         if(k%i==0){
19             s[cnt++]=i;
20             while(k%i==0){k/=i;}
21         }
22     }
23     if(k!=1){
24         s[cnt++]=k;
25     }
26     return;
27 }
28 ll all(ll k){
29     ll ans=0;
30     for(ll i=1;i<((ll)1<<cnt);i++){
31         ll sum=1,num1=0,tmp=i;
32         for(ll j=0;j<cnt;j++){
33             if(i&((ll)1<<j)){
34                 sum*=s[j];num1++;
35             }
36         }
37         tmp=k/sum;
38         if(num1&1){ans+=tmp;}
39         else{
40             ans-=tmp;
41         }
42     }
43     return ans;
44 }
45 int main(){
46     scanf("%d",&t);
47     while(t--){
48         scanf("%lld%lld",&n,&m);
49         ll k0=__gcd(n,m);
50         ll k1=n/k0;
51         ll k2=m/k0;//cout<<k1<<k2<<endl;
52         pan(k2);
53         printf("%lld\n",k2-all(k2+k1-(ll)1)+all(k1-(ll)1));
54     }
55     return 0;
56 }
View Code

猜你喜欢

转载自www.cnblogs.com/luoyugongxi/p/12243962.html