BZOJ-2751 [HAOI2012]容易题(easy)(计数)
题目描述
有一个长为 \(m\) 的序列 \(a\),\(\forall i\in[1,m],a_i\in [1,n]\),有 \(k\) 个限制条件,每个限制条件规定某个 $a_x $ 不能取 \(y\) 这个值,定义一个序列的积为该序列所有元素的乘积,求出所有可能的序列的积的和。
数据范围:\(n\leq 10^9,m\leq 10^9,k\leq 10^5,1\leq y\leq n,1\leq x\leq m\)。
分析
根据 乘法分配律,可以发现所有序列的积的和 \(=\) 每个位置的所有取值的和的积,答案即为 \(\big(\frac{n(n+1)}{2}\big)^m\)。
假设一共有 \(cnt\) 个 $ a_i $ 被限制,每个 \(a_i\) 被限制的数字之和为有 \(sum_i\),则一个被限制的 \(a_i\) 对答案的贡献为 \((\frac{n(n+1)}{2}-sum_i)\),所有被限制的 \(a_i\) 对答案的贡献为 \(\displaystyle\prod_{i=1}^{cnt}\Big(\frac{n(n+1)}{2}-sum_i)\),最后乘上没有被限制的数字的贡献,答案为:
\[\Big(\frac{n(n+1)}{2}\Big)^{m-cnt}·\displaystyle\prod_{i=1}^{cnt}\Big(\frac{n(n+1)}{2}-sum_i)
\]
注意去重。
代码
#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
map<pair<long long,long long>,long long > mp1;
map<long long,long long > mp2;
long long temp[200010];
long long quick_pow(long long a,long long b)
{
a=a%mod;
long long ans=1;
while(b)
{
if(b&1)
ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans%mod;
}
int main()
{
long long n,m,k,tot=0;
cin>>n>>m>>k;
while(k--)
{
long long x,y;
scanf("%lld %lld",&x,&y);
if(mp2[x]==0)
temp[++tot]=x;
if(mp1[make_pair(x,y)]==1)
continue;
mp1[make_pair(x,y)]=1;
mp2[x]+=y;
}
long long ans=1,sum=1ll*n*(n+1)/2;
for(int i=1;i<=tot;i++)
ans=ans%mod*((sum-mp2[temp[i]])%mod+mod)%mod;
cout<<ans%mod*quick_pow(sum,m-tot)%mod<<endl;
return 0;
}
posted on 2020-12-09 15:11 DestinHistoire 阅读(63) 评论(0) 编辑 收藏 举报