Solution -「CF 542D」Superhero's Job

cirnovsky /

link。

容易发现,如果将 xx 写作 i=1kpiαi\displaystyle \prod_{i = 1}^k p_i^{\alpha_i} 的形式,J(x)=1+piαi+piαipjαj+=T2SiTpiαi\displaystyle J(x) = 1+\sum p_i^{\alpha_i}+\sum\sum p_i^{\alpha_i}p_j^{\alpha_j}+\dots = \sum_{T \in 2^S} \sum_{i \in T} p_i^{\alpha_i},其中 S={1,,k}S = \{1, \dots, k\}。写到这里可以发现 Joker function 是个 multiplicative function,所以 Joker function 又可以写作 J(x)=i=1kJ(piαi)=i=1k(piαi+1)\displaystyle J(x) = \prod_{i = 1}^k J(p_i^{\alpha_i}) = \prod_{i = 1}^k \left(p_i^{\alpha_i}+1\right)

考虑 dp,设 f[i][j]f[i][j] 表示用前 ii 个因数通过上述形式凑出 jj 的方案数,转移很平凡,具体看代码。这个 dp 可以用数据结构来存。这个 dp 复杂度的保证在于 maxi[1,1012]σ0(i)=6720\displaystyle \max_{i \in [1, 10^{12}]} {\sigma_0(i)} = 6720,这就叫人比较无语。至于判断一个数是否是 pk+1p^k+1 的形式,可以根号分治来做,记阈值为 T=106T = 10^6,对于 T\leqslant T 的元素,可以线性筛出所有质数,标记所有质数的次幂,数量级粗略是 O(TlogT)O(T\log T),完全跑不满;对于 >T> T 的元素,因为 (T+1)2>1012(T+1)^2 > 10^{12},所以只需要判断是否为质数即可,Miller Rabin 或者其他 nb 的判素数方法即可。写不来 MR 所以直接蒯了个 mrsrz 的。

namespace Miller_Rabin{
	const int P[]={2,3,7,97,19260817};
	inline LL mul(LL a,LL b,const LL&md){
		LL tmp=a*b-(LL)((long double)a*b/md+.5)*md;
		return tmp+(tmp>>63&md);
	} 
	inline LL pow(LL a,LL b,const LL&md){
		LL ret=1;
		for(;b;b>>=1,a=mul(a,a,md))if(b&1)ret=mul(ret,a,md);
		return ret;
	}
	bool test(LL a,LL p){
		LL x=p-1;
		int d=0;
		while(!(x&1))++d,x>>=1;
		LL t=pow(a,x,p);
		while(d--){
			const LL ls=t;
			t=mul(t,t,p);
			if(t==1&&ls!=1&&ls!=p-1)return 0;
		}
		return t==1;
	}
	bool check(LL n){
		if(n<2)return 0;
		if(n==2||n==3||n==7||n==97||n==P[4])return 1;
		for(int i=0;i<5;++i)if(n%P[i]==0)return 0;
		for(int i=0;i<5;++i)
		if(!test(P[i]%n,n))return 0;
		return 1;
	}
}
using Miller_Rabin::check;
LL A;
bitset<1000100> tag;
int prm[1000100], cnt;
map<LL, int> mp; // a in it iff a = p^k
bastr<LL> offset[2000100];
void sieve(int n) {
    for (int i=2; i<=n; ++i) {
        if (!tag.test(i)) {
            prm[++cnt] = i;
        }
        for (int j=1; j<=cnt && i<=n/prm[j]; ++j) {
            tag.set(i*prm[j]);
            if (i%prm[j] == 0) {
                break;
            }
        }
    }
    for (int i=1; i<=cnt; ++i) {
        for (LL j=prm[i]; j<=1e12; j*=prm[i]) {
            mp[j] = i;
        }
    }
}
void executer() {
    cin >> A;
    map<LL, LL> dp[2];
    bastr<int> eff;
    for (LL i=1; i<=A/i; ++i) {
        if (A%i == 0) {
            if (mp.count(i-1)) {
                offset[mp[i-1]] += i;
                eff += mp[i-1];
            }
            if (i*i != A) {
                if (mp.count(A/i-1)) {
                    offset[mp[A/i-1]] += A/i;
                    eff += mp[A/i-1];
                }
                else if (check(A/i-1)) {
                    offset[++cnt] += A/i;
                    eff += cnt;
                }
            }
        }
    }
    sort(eff.begin(), eff.end());
    eff.erase(unique(eff.begin(), eff.end()), eff.end());
    dp[0][1] = 1;
    int cur = 1;
    for (auto u : eff) {
        dp[cur] = dp[cur^1];
        for (auto v : dp[cur^1]) {
            for (auto p : offset[u]) {
                if (A/p >= v.first && A%(v.first*p) == 0) {
                    dp[cur][v.first*p] += v.second;
                }
            }
        }
        cur ^= 1;
    }
    cout << dp[cs(eff)&1][A] << "\n";
}