[CF542D]Superhero's Job
阿新 • • 發佈:2019-01-04
[CF542D]Superhero's Job
題目大意:
定義函式
\[ J(x) = \sum_{\substack{1 \leq k \leq x \\ k \mid x \\ \gcd \left( k, x / k \right) = 1}} k \]
給定\(n(n\le10^{12})\),求方程\(J(x)=n\)的解的個數。
思路:
對於\(\gcd(a,b)=1\),\(J(ab)=J(a)J(b)\)。
對於\(p\in\mathbb{P}\),\(J(p^k)=p^k+1\)。
\(10^{12}\)內,約數最多的數\(\tau(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\n",f[d[0]]); return 0; }