2023 Jiangsu Collegiate Programming Contest, 2023 National Invitational of CCPC (Hunan), The 13th Xiangtan Collegiate Programming Contest

https://codeforces.com/gym/104396

E. LCM Plus GCD

题意

给定 x,kx,k,求满足条件的 (a1,a2,,ak)(a_1,a_2,\cdots,a_k) 的个数。

  • a1,a2,,aka_1,a_2,\cdots,a_k 各不相同。
  • gcd(a1,a2,,ak)+lcm(a1,a2,,ak)=x\gcd(a_1,a_2,\cdots,a_k)+\mathrm{lcm}(a_1,a_2,\cdots,a_k)=x

结果对 109+710^9+7 取模。

数据范围:1x,k1091\leq x,k\leq 10^9

题解

gcd(a1,a2,,ak)=g\gcd(a_1,a_2,\cdots,a_k)=g,记 lcm(a1,a2,,ak)=a×g\mathrm{lcm}(a_1,a_2,\cdots,a_k)=a\times g。则 (1+a)×g=x(1+a)\times g=x。枚举 gg,令 ai=aiga_i'=\dfrac{a_i}{g},则 gcd(a1,a2,,ak)=1,lcm(a1,a2,,ak)=a\gcd(a_1',a_2',\cdots,a_k')=1,\mathrm{lcm}(a_1',a_2',\cdots,a_k')=a。对 aaaia_i 做质因数分解,即 a=j=1mpjbj,ai=j=1mpjcija=\prod\limits_{j=1}^mp_j^{b_j},a_i=\prod\limits_{j=1}^mp_j^{c_{ij}}。那么,每个 cijc_{ij} 的取值一定在 [0,bj][0,b_j] 之间,同时,对每个 pjp_jmin{cij}=0,max{cij}=bj\min\{c_{ij}\}=0,\max\{c_{ij}\}=b_j。我们考虑容斥,一共有 2m2m 个约束,每个 pjp_j 对应两个约束。一般地,每个 pjp_j(1+bj)(1+b_j) 的贡献,但是如果它违反了一个约束,那么贡献要减少 11(因为 00bjb_j 将无法取到),违反两个就减少 22。然后把每个 pjp_j 的贡献相乘,就是总的取值可能,从中选 kk 个就可以了。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int p=1e9+7;
const int N=1e6+5;
int x,k;
ll fac[N],ifac[N];
void init()
{
fac[0]=1;
for(int i=1;i<N;i++) fac[i]=i*fac[i-1]%p;
ifac[0]=ifac[1]=1;
for(int i=2;i<N;i++) ifac[i]=(p-p/i)*ifac[p%i]%p;
for(int i=2;i<N;i++) ifac[i]=ifac[i]*ifac[i-1]%p;
}
ll C(int n,int m)
{
if(n<m) return 0;
return fac[n]*ifac[m]%p*ifac[n-m]%p;
}
ll solve(int g)
{
int a=x/g-1;
if(a==0) return 0;
vector<pii> fac;
for(int i=2;i*i<=a;i++)
if(a%i==0)
{
int cnt=0;
while(a%i==0)
{
cnt++;
a/=i;
}
fac.push_back({i,cnt});
}
if(a>1) fac.push_back({a,1});
int n=(int)fac.size();
ll sum=0;
for(int i=0;i<(1<<n);i++)
for(int j=0;j<(1<<n);j++)
{
int op=1,res=1;
for(int k=0;k<n;k++)
{
int v=fac[k].second+1;
if(i>>k&1)
{
op*=-1;
v--;
}
if(j>>k&1)
{
op*=-1;
v--;
}
res*=v;
}
sum=(sum+C(res,k)*op+p)%p;
}
return sum;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
init();
cin>>x>>k;
ll ans=0;
for(int i=1;i*i<=x;i++)
if(x%i==0)
{
ans=(ans+solve(i))%p;
if(i*i!=x) ans=(ans+solve(x/i))%p;
}
cout<<ans<<'\n';
return 0;
}

2023 Jiangsu Collegiate Programming Contest, 2023 National Invitational of CCPC (Hunan), The 13th Xiangtan Collegiate Programming Contest
https://je3ter.github.io/2023/09/10/ACM/2023 Jiangsu Collegiate Programming Contest, 2023 National Invitational of CCPC (Hunan), The 13th Xiangtan Collegiate Programming Contest/
作者
Je3ter
发布于
2023年9月10日
许可协议