Description
小A得到了一个数列A,他告诉你这个数列中所有的A[i]都是1到n的自然数,并且告诉你对于一些A[i]不能取哪些值。无聊的你想要知道所有可能的数列的积的和。定义一个数列的积为这个数列所有数的乘机。由于答案太大,只要模10^9+7输出即可。
Input
第一行三个整数n,m,k,分别表示数列元素取值范围,数列长度以及限制的数量。
接下来k行每行两个正整数x,y,表示A[x]的值不可能是y。
Output
一行一个整数表示答案。如果连一种可能的数列都没有,就输出0即可。
Sample Input
3 4 5
1 1
1 1
2 2
2 3
4 3
Sample Output
90
Hint
对于前30%的数据,n<=4,m<=10,k<=10
另有20%的数据k=0
对于70%的数据n<=1000,m<=1000,k<=1000
对于100%的数据,n<=109,m<=109,k<=105,1<=y<=n,1<=x<=m
做法:考虑每个限制的部分对答案的贡献,其余部分直接求解,最后相加即可。
代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#define maxn 1000000007
using namespace std;
long long n,m,k,ans,a[200007];
struct arr
{
long long x,y;
}f[200007];
long long pow1(long long a,long long b)
{
long long r=1,base=a;
while(b)
{
if(b&1) r*=base%maxn;
r%=maxn;
base*=base;
base%=maxn;
b>>=1;
}
return r;
}
long long cmp (arr a,arr b)
{
return(a.x<b.x) || (a.x==b.x && a.y<b.y);
}
int main()
{
cin>>n>>m>>k;
for (long long i=1;i<=k;i++)
scanf("%I64d%I64d",&f[i].x,&f[i].y);
ans=(((n+1)*n)/2) % maxn;
sort(f+1,f+k+1,cmp);
long long e=0;
for (long long i=1;i<=k;i++)
{
if (f[i].x==f[i-1].x && f[i].y==f[i-1].y) continue;
else
{
if (f[i].x==f[i-1].x)
{
a[e]+=f[i].y;
a[e]%=maxn;
}
else
{
e++;
a[e]+=f[i].y;
a[e]%=maxn;
}
}
}
long long ans2=pow1(ans,m-e)%maxn;
long long ans3=1;
for (int i=1;i<=e;i++)
{
ans3*=((((n+1)*n)/2)-a[i])%maxn;
ans3%=maxn;
}
ans3%=maxn;
ans2%=maxn;
long long answer=(ans2*ans3)%maxn;
cout<<answer;
}