https://www.luogu.org/problemnew/show/P2231
题意相当于:
有n个位置a[1..n],每个位置可以填[1,m]中任一个整数,问共有多少种填法满足gcd(a[1],a[2],..,a[n],m)=1
可以反演一下

1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<vector> 5 #include<cmath> 6 using namespace std; 7 #define fi first 8 #define se second 9 #define mp make_pair 10 #define pb push_back 11 typedef long long ll; 12 typedef unsigned long long ull; 13 typedef pair<int,int> pii; 14 const ll N=10000; 15 ll prime[N+10],len; 16 bool nprime[N+10]; 17 ll ans; 18 ll poww(ll a,ll b) 19 { 20 ll bs=a,an=1; 21 for(;b;b>>=1,bs*=bs) 22 if(b&1) 23 an*=bs; 24 return an; 25 } 26 ll getmu(ll x) 27 { 28 ll i,ans=1,ed=sqrt(x+0.5); 29 bool fl; 30 for(i=1;i<=len&&prime[i]<=ed;i++) 31 { 32 fl=0; 33 while(x%prime[i]==0) 34 { 35 if(fl) return 0; 36 fl=1; 37 x/=prime[i]; 38 ans*=(-1); 39 } 40 } 41 if(x!=1) ans*=(-1); 42 return ans; 43 } 44 ll n,m; 45 void work(ll d) 46 { 47 ans+=poww(m/d,n)*getmu(d); 48 } 49 int main() 50 { 51 ll i,j; 52 for(i=2;i<=N;i++) 53 { 54 if(!nprime[i]) prime[++len]=i; 55 for(j=1;j<=len&&i*prime[j]<=N;j++) 56 { 57 nprime[i*prime[j]]=1; 58 if(i%prime[j]==0) break; 59 } 60 } 61 scanf("%lld%lld",&n,&m); 62 ll ed=sqrt(m+0.5); 63 for(i=1;i<=ed;i++) 64 if(m%i==0) 65 { 66 work(i); 67 if(m/i!=i) work(m/i); 68 } 69 printf("%lld",ans); 70 return 0; 71 }