[http://codeforces.com/problemset/problem/900/D]
有这样的序列 a 1 , a 2 , a 3 ⋅ ⋅ ⋅ a n a_{1},a_{2},a_{3}···a_{n} a1,a2,a3⋅⋅⋅an 使得他们的和为 y y y ,最大公因数为 x x x,问满足这样的序列有多少个。
练习题里的题,我原来根本看不出是莫比乌斯反演。
显然对于每个 a i a_{i} ai 都是 x x x 的倍数,于是 y y y 是 x x x 的倍数。
如果不考虑最大公因数是 x x x 这个条件的话,把每个 a i a_{i} ai 都除以 x x x,就是纯粹的有序整数拆分问题,也就是 2 y x − 1 2^{\frac{y}{x}-1} 2xy−1。
但这显然是 ∑ d ∣ y x [ gcd = d ] \sum_{d|\frac{y}{x}}[\gcd=d] ∑d∣xy[gcd=d] 的情况数,所以我们要去掉 ∑ [ gcd ≠ 1 ] \sum[\gcd\neq 1] ∑[gcd̸=1] 的情况,也就是 ∑ d ∣ y x [ gcd = d & & d ! = 1 ] \sum_{d|\frac{y}{x}}[\gcd=d \&\& d!=1] ∑d∣xy[gcd=d&&d!=1] 的情况。
上面是一种思路,另一种思路就是莫比乌斯反演了,如果我们用 f ( n ) f(n) f(n) 表示 ∑ n ∣ y x [ gcd = n ] \sum_{n|\frac{y}{x}}[\gcd=n] ∑n∣xy[gcd=n]。
那么我们就是要求 f ( 1 ) f(1) f(1),然后他的倍数和 F ( n ) = ∑ n ∣ d f ( d ) F(n)=\sum_{n|d}f(d) F(n)=∑n∣df(d) 就表示 ∑ n ∣ y x [ n ∣ gcd ] \sum_{n|\frac{y}{x}}[n|\gcd] ∑n∣xy[n∣gcd] 的情况数了,也就是 2 y x n − 1 2^{\frac{\frac{y}{x}}{n}-1} 2nxy−1 种情况,所以我们也直接枚举莫比乌斯函数值不为0的约数就可以了。
#include
using namespace std;
typedef long long ll;
const int maxn=1e6+7;
const int mod=1e9+7;
int yue[maxn],numy,n;
ll ans;
ll power(ll a,ll b){
ll ans=1;
while(b){
if(b&1)ans=(ans*a)%mod;
a=(a*a)%mod;
b>>=1;
}
return ans;
}
void dfs(int len,int mu,ll s){
if(len>numy){
ans=((ans+(ll)mu*power(2,n/s-1))%mod+mod)%mod;
return;
}
dfs(len+1,mu,s);
dfs(len+1,-mu,s*yue[len]);
}
int main(){
#ifdef LOCAL
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif // LOCAL
ios::sync_with_stdio(false);
int x,y;
while(cin>>x>>y){
if(y%x){
cout<<0<<endl;
continue;
}
numy=0;ans=0;
n=y/x;int tmp=n;
for(int i=2;i<=n;i++)
if(n%i==0){
yue[++numy]=i;
while(n%i==0)
n/=i;
}
n=tmp;
dfs(1,1,1);
cout<<ans<<endl;
}
}