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