[CF542D]Superhero's Job [CF542D]Superhero's Job
题目大意:
定义函数
[J(x) = sum_{substack{1 leq k leq x \ k mid x \ gcd left( k, x / k
ight) = 1}} k
]
给定(n(nle10^{12})),求方程(J(x)=n)的解的个数。
思路:
对于(gcd(a,b)=1),(J(ab)=J(a)J(b))。
对于(pinmathbb{P}),(J(p^k)=p^k+1)。
(10^{12})内,约数最多的数( au(963761198400)=6720)。
DP:(f[i])表示组成第(i)种有用的约数的方案数。
源代码:
#include<map>
#include<cstdio>
#include<cctype>
#include<vector>
#include<algorithm>
typedef long long int64;
inline int64 getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int64 x=ch^'0';
while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
return x;
}
const int D=6721;
std::vector<int64> p;
std::map<int64,int> map;
int64 d[D],f[D];
int main() {
const int64 n=getint();
for(register int64 i=1;i*i<=n;i++) {
if(n%i) continue;
d[++d[0]]=i;
if(i*i!=n) d[++d[0]]=n/i;
}
std::sort(&d[1],&d[d[0]]+1);
for(register int i=1;i<=d[0];i++) {
map[d[i]]=i;
int64 x=d[i]-1;
for(register int64 j=2;j*j<=x;j++) {
if(x%j) continue;
while(x%j==0) x/=j;
if(x==1) p.push_back(j);
}
if(x>1) p.push_back(x);
}
std::sort(p.begin(),p.end());
p.resize(std::unique(p.begin(),p.end())-p.begin());
const int m=p.size();
f[1]=1;
for(register int i=0;i<m;i++) {
for(register int j=d[0];j;j--) {
int64 t=p[i];
while(t<d[j]) {
if(d[j]%(t+1)==0) {
f[j]+=f[map[d[j]/(t+1)]];
}
t*=p[i];
}
}
}
printf("%lld
",f[d[0]]);
return 0;
}