洛谷 P2231 [HNOI2002]跳蚤

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 }
View Code
原文地址:https://www.cnblogs.com/hehe54321/p/9792695.html