[CF542D]Superhero's Job

本文解析了Codeforces竞赛中题目CF542D的解题思路与算法实现,详细介绍了如何通过数学性质和动态规划求解特定函数的解的个数。

[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;
}

转载于:https://www.cnblogs.com/skylee03/p/10219415.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值