BZOJ3331 BeiJing2013 压力 树上差分 圆方树

版权声明:本文为博主原创文章,可以转载但是必须声明版权。 https://blog.csdn.net/forever_shi/article/details/88878384

题目链接

题意:
你有一个 n n 个点 m m 条边的无向连通图,有 q q 次操作,每次给出两个点 x , y x,y x x y y 的路径上必须经过的点的权值加一,问你最后每一个点的权值。 n , m , q < = 2 e 5 n,m,q<=2e5

题解:
无向图上路径问题还是转成圆方树上路径问题来搞。然后这个题比较简单,思考一下就会发现其实就是圆方树的路径上的圆点个数。那么我们对于一次操作,树上差分一下,最后dfs一遍算出每个点的答案就可以了。

代码:

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

long long n,k;
const long long mod=1000000007;
long long jie[1000010],ni[1000010],ans;
inline long long ksm(long long x,long long y,long long mod)
{
	long long res=1;
	while(y)
	{
		if(y&1)
		res=res*x%mod;
		x=x*x%mod;
		y>>=1;
	}
	return res;
}
int main()
{
	scanf("%lld%lld",&n,&k);
	jie[0]=1;
	for(long long i=1;i<=n;++i)
	jie[i]=jie[i-1]*i%mod;
	ni[n]=ksm(jie[n],mod-2,mod);
	for(long long i=n-1;i>=0;--i)
	ni[i]=ni[i+1]*(i+1)%mod;
	for(long long i=n;i>=k;--i)
	{
		if((i-k)&1)
		ans=(ans-(ksm(2ll,ksm(2ll,n-i,mod-1),mod)-1ll+mod)%mod*jie[i]%mod*ni[k]%mod*ni[i-k]%mod*jie[n]%mod*ni[i]%mod*ni[n-i]%mod+mod)%mod;
		else
		ans=(ans+(ksm(2ll,ksm(2ll,n-i,mod-1),mod)-1ll+mod)%mod*jie[i]%mod*ni[k]%mod*ni[i-k]%mod*jie[n]%mod*ni[i]%mod*ni[n-i]%mod)%mod;
	}
	printf("%lld\n",ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/forever_shi/article/details/88878384