1. 程式人生 > >【CF900D】Unusual Sequences 容斥(莫比烏斯反演)

【CF900D】Unusual Sequences 容斥(莫比烏斯反演)

div blog mic names include sin 題意 方案 ace

【CF900D】Unusual Sequences

題意:定義正整數序列$a_1,a_2...a_n$是合法的,當且僅當$gcd(a_1,a_2...a_n)=x$且$a_1+a_2+...+a_n=y$。給定x,y,求合法的序列總數。

x,y<=10^9。

題解:不難想到容斥,先不管gcd的限制,那麽總方案數就是$2^{y-1}$。你可以理解為有y個1,除了第一個1,其余的要麽加到上一個數中去,要麽自己變成一個新數。

如果考慮gcd的限制呢?容斥一發即可。並且容斥系數就是我們常用的莫比烏斯函數。

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
typedef long long ll;
const ll P=1000000007;
int n,m,tot;
ll ans;
int p[10];
inline ll pm(ll x,ll y)
{
	ll z=1;
	while(y)
	{
		if(y&1)	z=z*x%P;
		x=x*x%P,y>>=1;
	}
	return z;
}
void dfs(int x,int y,int z)
{
	if(x>tot)
	{
		ans=(ans+P+pm(2,n/y-1)*z%P)%P;
		return ;
	}
	dfs(x+1,y,z),dfs(x+1,y*p[x],-z);
}
int main()
{
	scanf("%d%d",&m,&n);
	if(n%m)
	{
		puts("0");
		return 0;
	}
	n/=m;
	int i,t=n;
	for(i=2;i*i<=t;i++)	if(t%i==0)
	{
		p[++tot]=i;
		while(t%i==0)	t/=i;
	}
	if(t!=1)	p[++tot]=t;
	dfs(1,1,1);
	printf("%I64d",ans);
	return 0;
}

【CF900D】Unusual Sequences 容斥(莫比烏斯反演)