[HAOI2012] 容易题

有一个数列A已知对于所有的A[i]都是1~n的自然数,并且知道对于一些A[i]不能取哪些值,我们定义一个数列的积为该数列所有元素的乘积,要求你求出所有可能的数列的积的和 mod 1000000007的值

n<=10^9,m<=10^9,k<=10^5,1<=y<=n,1<=x<=m

Solution

还真是个容易题

首先每个位置对答案的贡献独立,那么我们可以把顺序换一下

先考虑所有不受限制的位置,假设有 (m-tot) 个,那么它们的贡献是 ((n(n+1)/2)^{m-tot})

在考虑受限的位置,一个位置不取哪些数,如果它们的和为 (s),这个位置的贡献就是 (n(n+1)/2 - s)

最后都乘起来即可

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define ll long long
const int mod = 1000000007;
const int N = 1000005;
#define modulo mod
ll qpow(ll p,ll q) {
    ll r = 1;
    for(; q; p*=p, p%=modulo, q>>=1) if(q&1) r*=p, r%=modulo;
    return r;
}

int n,m,k;
map <int,int> mp;
struct limit {
    int x,y;
    bool operator < (const limit &b) const {
        return x==b.x?(y<b.y):(x<b.x);
    }
    bool operator != (const limit &b) const {
        return x!=b.x || y!=b.y;
    }
} l[N];

signed main() {
    ios::sync_with_stdio(false);
    cin>>n>>m>>k;
    for(int i=1;i<=k;i++) {
        int x,y;
        cin>>x>>y;
        l[i].x=x;
        l[i].y=y;
    }
    sort(l+1,l+k+1);
    for(int i=1;i<=k;i++) {
        if(l[i]!=l[i-1]) mp[l[i].x]+=l[i].y;
    }
    int ans=qpow((n*(n+1)/2)%mod,m-mp.size());
    for(map<int,int>::iterator it=mp.begin();it!=mp.end();it++) {
        ans*=((n*(n+1)/2-it->second)%mod+mod)%mod;
        ans%=mod;
    }
    cout<<ans;
}

原文地址:https://www.cnblogs.com/mollnn/p/12299623.html