bzoj 2751: [HAOI2012]容易题(easy)
Description
为了使得大家高兴,小Q特意出个自认为的简单题(easy)来满足大家,这道简单题是描述如下:
有一个数列A已知对于所有的A[i]都是1~n的自然数,并且知道对于一些A[i]不能取哪些值,我们定义一个数列的积为该数列所有元素的乘积,要求你求出所有可能的数列的积的和 mod 1000000007的值,是不是很简单呢?呵呵!
solution
容易发现,我们要求的东西就是 $$(P11+P12+P13...)(P21+P22+P23...)(P31+P32+P33...)$$
对应样例中的每一项,对于有限制的部分我们暴力算,没有限制的部分就用快速幂算一下即可
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#define RG register
#define il inline
#define iter iterator
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
const int mod=1000000007;
const int N=100005;
ll n,m,k,p[N],q[N];
struct node{
ll x,y;
bool operator <(const node &pr)const{
if(x!=pr.x)return x<pr.x;
return y<pr.y;
}
}a[N];
il ll qm(ll x,ll k){
ll sum=1;
while(k){
if(k&1)sum*=x,sum%=mod;
x*=x;x%=mod;k>>=1;
}
return sum;
}
void work()
{
cin>>n>>m>>k;
for(int i=1;i<=k;i++)
scanf("%lld%lld",&a[i].x,&a[i].y);
sort(a+1,a+k+1);
ll sum=0,mul,ans=1;
for(int i=1;i<=k;i++){
int j=i;
while(j<k && a[j+1].x==a[i].x)j++;
mul=n*(n+1)>>1;
mul-=a[i].y;
for(int g=i+1;g<=j;g++)
if(a[g].y!=a[g-1].y)mul-=a[g].y;
ans*=mul%mod;ans%=mod;
i=j;sum++;
}
mul=n*(n+1)>>1;mul%=mod;
ll ret=qm(mul,m-sum);
ans*=ret;ans%=mod;
printf("%lld\n",ans);
}
int main()
{
work();
return 0;
}