算一个数字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 }
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 }
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 }