【莫反】CF900D Unusual Sequences 做题记录

从一个 dp 题单点进去的,往 dp 上想了半天,啥都没想出来,看了个题解,发现可以莫反做,于是重新思考。

先考虑无解的情况,很明显,\(x \nmid y\) 时,是不存在合法的构造的。往简化的方向走,设 \(sum=y \div x\),那么题目可以转化为满足 \(\sum_{i=1}^{n}a_i=sum\) \(\gcd(a_1,a_2,a_3,...,a_n)=1\) 的数列的个数。考虑设 \(g(x)\)\(\sum_{i=1}^{n}a_i=x\) 的个数,考虑使用隔板法求 \(g(x)\)

\[g(x)=\sum_{i=1}^{n}\binom{x-1}{i-1}=2^{x-1} \]

\(f(x)\) 为满足 \(\sum_{i=1}^{n}a_i=x\) \(\gcd(a_1,...,a_n)=1\) 的数列个数,根据反演,\(g(x)=\sum_{d \mid x}f(d)\),那么:

\[f(x)=\sum_{d \mid x}g(\frac{x}{d})\mu(d) \]

显然,本题答案为 \(f(sum)\)

\(Code\)

点击查看代码
/*
	考虑无解,当y%x!=0时无解
	考虑设gcd为1,隔板法求方案数
	考虑莫反
	容斥是什么神仙做法/fad 
	线性筛复杂度达到了1e9
	似乎会T
	考虑求单个 
*/
#include <bits/stdc++.h>

using namespace std;

#define int long long
#define mod (int)(1e9+7)

inline int mu(int x){
    int prid=0;
    int sq=0;
    for(int i=2;i*i<=x;++i){
        if(x%i) continue;
        sq=0;
        prid++;
        while(x%i==0){x/=i;sq++;}
        if(sq>=2) return 0;
    }
    x==1?:prid++;
    return (prid&1)?mod-1:1;
}

inline int qpow(int a,int b){
	int res=1;
	while(b){
		if(b&1) res=res*a%mod;
		b>>=1;a=a*a%mod;
	}
	return res;
}

signed main(){
	int x,y,ans=0;
	scanf("%lld %lld",&x,&y);
	if(y%x) return puts("0"),0;
	int n=y/x;
	for(int i=1;i*i<=n;++i){
		if(!(n%i)){
			ans=(ans+qpow(2,i-1)*mu(n/i)%mod)%mod;
			if(i*i!=n) ans=(ans+qpow(2,n/i-1)*mu(i)%mod)%mod;
		}
	}
	printf("%lld\n",ans);
	return 0; 
}
posted @ 2022-08-07 22:56  Akane_Moon  阅读(37)  评论(0)    收藏  举报

“一言(ヒトコト)