DestinHistoire

 

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编辑  收藏  举报

导航