质因子和容斥原理

算一个数字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<){
18         ll sum=1,num1=0,tmp;
19         for(ll j=0;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
 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<){
31         ll sum=1,num1=0,tmp=i;
32         for(ll j=0;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<
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/k ~ (n+m-1)/k之中有多少跟 m/k 互质的数

 1 #include
 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<){
31         ll sum=1,num1=0,tmp=i;
32         for(ll j=0;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<
52         pan(k2);
53         printf("%lld\n",k2-all(k2+k1-(ll)1)+all(k1-(ll)1));
54     }
55     return 0;
56 }
View Code

 

 

欧拉函数 φ(n)  是小于等于 n 且与  n 互素的正整数的个数

n=p1^a1*p2^a2…pk^ak (p是质素)
 
就有  φ(n)=n*( 1 - 1/p1 )*( 1 - 1/p2 )…( 1 - 1/pk)
 
 
upd:
看了别人的博客,发现 D 题居然就是欧拉函数模板,好神奇.jpg!!!
 1 #include
 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=2e5+10;
10 ll n,t,m;
11 int main(){
12     scanf("%lld",&t);
13     while(t--){
14         scanf("%lld%lld",&n,&m);
15         ll k=__gcd(n,m);
16         n/=k,m/=k;
17         ll ans=m;
18         for(ll i=2;i*i<=m;i++){
19             if(m%i==0){
20                 while(m%i==0){m/=i;}
21                 ans=ans/i*(i-1);
22             }
23         }
24         if(m!=1){
25             ans=ans/m*(m-1);
26         }
27         printf("%lld\n",ans);
28     }
29     return 0;
30 }
View Code

让我好好想想

 upd2:
n~n+m-1%m等效于0~m-1,就是求欧拉函数
 

你可能感兴趣的:(质因子和容斥原理)