cf678div2 F Sum Over Subsets

upd:做了这题去复习了一下反演,发现这就是反演的基本公式
F [ n ] = ∑ d ∣ n f [ d ] 则 f [ n ] = ∑ d ∣ n μ [ d ] ∗ F [ n / d ] F[n]=\sum_{d|n}f[d]\\ 则f[n]=\sum_{d|n}\mu[d]*F[n/d] F[n]=dnf[d]f[n]=dnμ[d]F[n/d]
理解的话就是F[n]是任取,f[n]是取gcd为n的。
下面是原文:

题意:

给一个n的集合S,对所有满足下列3个条件的集合对(A,B),求
∏ A , B ∑ x ∈ A x ∗ ∑ x ∈ B x \prod_{A,B} \sum_{x\in A} x * \sum_{x\in B} x A,BxAxxBx
3个条件:
1. g c d ( A ) = 1 2. ∣ A ∣ = ∣ B ∣ + 1 3. B ⊂ A 1.gcd(A)=1 \\ 2.|A|=|B|+1\\ 3.B\subset A\\ 1.gcd(A)=12.A=B+13.BA

解:

1.首先把集合B消去:
∑ x ∈ A x ∗ ∑ x ∈ B x = ∑ x ∈ A x ∗ ∑ x ∈ A x ∗ ( ∣ A ∣ − 1 ) ( B 中 每 个 元 素 的 贡 献 都 是 ∣ A ∣ − 1 次 ) \sum_{x\in A} x * \sum_{x\in B} x\\ =\sum_{x\in A} x * \sum_{x\in A} x *(|A|-1)\\(B中每个元素的贡献都是|A|-1次) xAxxBx=xAxxAx(A1)(BA1)
2.然后考虑 gcd(A) = 1这个条件,可以用容斥做:
记 f ( S ) 为 在 集 合 S 中 任 取 集 合 A 的 答 案 答 案 = ∑ g c d ( S ) = p , p ∈ p r i m e μ [ p ] ∗ f ( S ) 记f(S)为在集合S中任取集合A的答案\\ 答案=\\ \sum_{gcd(S)=p,p\in prime} \mu[p]*f(S) f(S)SA=gcd(S)=p,pprimeμ[p]f(S)
可以这么理解:在原集合中任取,取多了gcd不为1的集合,所以把所有gcd为所有质数的都减掉,又以类似6=2*3这样的数为gcd的集合被减多了,所以加回来…………

3.所以问题就变成了求 f(S) ;

设集合S中的元素为{a1,a2,……an} (这里的集合是multiset,可以有重复元素)

还是考虑每个元素的贡献(以a1为例)
先 把 总 的 式 子 列 出 来 1 ∗ ∑ 2 < = i < = n , i < j < = n ( a [ i ] + a [ j ] ) 2 + 2 ∗ ∑ 2 < = i < = n , i < j < = n , j < k < = n ( a [ i ] + a [ j ] + a [ k ] ) 2 + … … … … 然 后 只 考 虑 包 含 a [ 1 ] 的 部 分 : 第 一 部 分 平 方 的 部 分 : ∑ 1 < = i < = n − 1 i ∗ C n − 1 i ∗ a [ 1 ] 2 = ( n − 1 ) ∗ 2 n − 2 ∗ a [ 1 ] 2 ( 看 成 ( 1 + x ) n − 1 求 导 后 令 x = 1 ) 所 以 第 一 部 分 就 完 成 了 然 后 是 第 二 部 分 非 平 方 的 部 分 : 1 ∗ a [ 1 ] ∗ ∑ 2 < = i < = n a [ i ] + 2 ∗ a [ 1 ] ∗ ∑ 2 < = i < = n , i < j < = n ( a [ i ] + a [ j ] ) + 3 ∗ a [ 1 ] ∗ ∑ 2 < = i < = n , i < j < = n , j < k < = n ( a [ i ] + a [ j ] + a [ k ] ) + … … … … = 1 ∗ a [ 1 ] ∗ C n − 2 0 ∑ 2 < = i < = n a [ i ] + 2 ∗ a [ 1 ] ∗ C n − 2 1 ∑ 2 < = i < = n a [ i ] + 3 ∗ a [ 1 ] ∗ C n − 2 2 ∑ 2 < = i < = n a [ i ] + … … … … = a [ 1 ] ∗ ∑ 2 < = i < = n a [ i ] ∗ ∑ 0 < = i < = n − 2 ( i + 1 ) ∗ C n − 2 i = a [ 1 ] ∗ ( ∑ 2 < = i < = n a [ i ] ) ∗ 2 n − 3 ∗ ( 2 ∗ n − 3 ) ( 上 面 这 一 步 看 成 x ∗ ( 1 + x ) n − 2 求 导 后 令 x = 1 ) 所 以 这 一 部 分 也 完 成 了 先把总的式子列出来\\ 1*\sum_{2<=i<=n,i<j<=n}(a[i]+a[j])^2+\\ 2*\sum_{2<=i<=n,i<j<=n,j<k<=n}(a[i]+a[j]+a[k])^2+\\ …………\\ 然后只考虑包含a[1]的部分:\\ 第一部分平方的部分:\\ \sum_{1<=i<=n-1}i*C_{n-1}^{i}*a[1]^2\\ =(n-1)*2^{n-2}*a[1]^2 (看成(1+x)^{n-1}求导后令x=1)\\ 所以第一部分就完成了\\ 然后是第二部分非平方的部分:\\ 1*a[1]*\sum_{2<=i<=n}a[i] +\\ 2*a[1]*\sum_{2<=i<=n,i<j<=n}(a[i]+a[j])+\\ 3*a[1]*\sum_{2<=i<=n,i<j<=n,j<k<=n}(a[i]+a[j]+a[k])+\\ …………\\ =1*a[1]*C_{n-2}^{0}\sum_{2<=i<=n}a[i] +\\ 2*a[1]*C_{n-2}^{1}\sum_{2<=i<=n}a[i] +\\ 3*a[1]*C_{n-2}^{2}\sum_{2<=i<=n}a[i] +\\ …………\\ =a[1]*\sum_{2<=i<=n}a[i]*\sum_{0<=i<=n-2}(i+1)*C_{n-2}^{i}\\ =a[1]*(\sum_{2<=i<=n}a[i])*2^{n-3}*(2*n-3)\\ (上面这一步看成x*(1+x)^{n-2}求导后令x=1)\\ 所以这一部分也完成了 12<=i<=n,i<j<=n(a[i]+a[j])2+22<=i<=n,i<j<=n,j<k<=n(a[i]+a[j]+a[k])2+a[1]1<=i<=n1iCn1ia[1]2=(n1)2n2a[1]2((1+x)n1x=1)1a[1]2<=i<=na[i]+2a[1]2<=i<=n,i<j<=n(a[i]+a[j])+3a[1]2<=i<=n,i<j<=n,j<k<=n(a[i]+a[j]+a[k])+=1a[1]Cn202<=i<=na[i]+2a[1]Cn212<=i<=na[i]+3a[1]Cn222<=i<=na[i]+=a[1]2<=i<=na[i]0<=i<=n2(i+1)Cn2i=a[1](2<=i<=na[i])2n3(2n3)(x(1+x)n2x=1)

代码

#include <bits/stdc++.h>
using namespace std;

#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef long long ll;
typedef double db;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef pair<long long,int> PLI;
const ll mod=998244353;
//mt19937_64 mrand(random_device{}()); 
//int rnd(int x) { return mrand() % x;}
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}

int v[100066];
VI prime;
int mu[100066];

void init()
{
	int N=100000;
	for(int i=2;i<=N;i++)
	{
		if(!v[i])
		{
			mu[i]=1;
			v[i]=i;
			prime.pb(i);
		}
		for(auto p:prime)
		{
			if(p>v[i]||i>N/p)break;
			v[i*p]=p;
			if(i%p==0)mu[i*p]=0;
			else mu[i*p]=-mu[i];
		}
	}
}


ll solve(vector<PII>vec)
{
	ll sum=0,all=0;
	ll all1=0;
	for(auto x:vec)
	{
		sum=(sum+1ll*x.fi*x.se)%mod;
		all=(all+x.se)%mod;
		all1=(all1+x.se)%(mod-1);
	}
	ll pp=powmod(2,all1-2+mod-1)*((all-1+mod)%mod)%mod;
	ll ret=0;

	ll two0=powmod(2,all1-3+mod-1);
	ll two1=two0*2%mod;
	ll two2=two1*2%mod;
	//ll qq=two0-two2*powmod(all,mod-2)%mod+mod+two1*powmod(all-1,mod-2)%mod-powmod(all,mod-2)*powmod(all-1,mod-2)%mod+mod;
	//qq%=mod;
	//qq=qq*2%mod;
	ll qq=two1+(all-2+mod)*two0;
	qq=qq%mod;
	//printf("___________ %lld %lld %lld__\n",all1,two0,qq);
	for(auto x:vec)
	{
		ret+=pp*x.fi%mod*x.fi%mod*x.se%mod;
		ret%=mod;
		ll tmp=(sum+mod-x.fi)%mod;
		tmp=1ll*x.se*x.fi%mod*tmp%mod*qq%mod;
		ret=(ret+tmp)%mod;
	}
	return ret;
}

int n;
vector<PII>vec,V[100066];

int main()
{
	init();
	scanf("%d",&n);
	int x,y;
	for(int i=1;i<=n;i++)
	{
		scanf("%d%d",&x,&y);
		vec.pb(mp(x,y));
		for(int j=1;1ll*j*j<=x;j++)
		{
			if(x%j)continue;
			V[j].pb(mp(x,y));
			if(x/j!=j)V[x/j].pb(mp(x,y));
		}
	}
	ll ans=solve(vec);
	//printf("%lld__\n",ans);
	//return 0;
	for(int i=2;i<=100000;i++)
	{
		ll tmp=(-solve(V[i])*mu[i]+mod)%mod;
		//printf("%d : %lld\n",i,tmp);
		ans=(ans+tmp)%mod;
	}
	printf("%lld\n",ans);
	return 0;
}

/*
3
6 1
2 1
3 1

122

*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值