2017年8月10日提高组T1 数学

来源:互联网 发布:中国数据分析行业协会 编辑:程序博客网 时间:2024/05/16 11:02

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

分析:
答案为a[1]a[2]* ……*a[m]
{a[i]为第i位可以选的数的和}

证明一下:
设集合Ai为到k节点时,所有数列的积,这里的积不止一个。设sum[i]为所有的积的和。对于其中一个序列j,有
A[i,j]=A[i-1,j]*1+A[i-1,j]*2+……+A[i-1,j]*n
{除了那些不能选的}

设t为能选的数的和。有A[i,j]=A[i-1,j]*t

对于每个序列都有以上的规律。
有sum[i]=A[i-1,1]*t+A[i-1,2]*t+……+A[i-1,k]*t
{k为序列数,可以不理}

因为 sum[i-1]=A[i-1,1]+A[i-1,2]+……+A[i-1,k]

则sum[i]=sum[i-1]*t

那对于结论,可以先预处理出num为1~n的和,有
num=(1+n)*n/2
我们可以用这个去减那些不能用的,因为不能用的条件只要10^5个。

我们考虑N=10^9, 那至少有10^9-10^5个数和就是num,对于这些数,快速幂即可。

最后排序去重。

代码:

const modd=1000000007;var n,m,k,sum,ans,t,p:int64; a:array [0..100011,1..2] of longint; i,x,y:longint;procedure qsort(l,r:longint);  var    key,temp,key1:int64;    mid,i,j:longint;  begin    if l>=r then exit;    i:=l;j:=r;    mid:=(l+r) shr 1;    key:=a[mid,1];    key1:=a[mid,2];    repeat      while  (a[i,1]<key) or (a[i,1]=key) and (a[i,2]<key1) do inc(i);      while  (a[j,1]>key) or (a[j,1]=key) and (a[j,2]>key1) do dec(j);      if i<=j then      begin        temp:=a[i,1];a[i,1]:=a[j,1];a[j,1]:=temp;        temp:=a[i,2];a[i,2]:=a[j,2];a[j,2]:=temp;        inc(i);dec(j);      end;    until i>j;    qsort(l,j);    qsort(i,r);  end;function power(x,r:int64):int64;var g:int64; begin  if r=1 then exit(x);  if r=0 then exit(1);  g:=power(x,r shr 1);  g:=g*g mod modd;  if odd(r) then g:=g*x mod modd;  exit(g); end;begin readln(n,m,k); sum:=((n+1)*n div 2) mod modd; for i:=1 to k do   read(a[i,1],a[i,2]); qsort(1,k); ans:=1; p:=1; for i:=1 to k do  begin   if a[i,1]<>a[i-1,1] then    begin     inc(t);     ans:=(ans*p) mod modd;     p:=(sum+modd-a[i,2]) mod modd;    end   else     if a[i,2]<>a[i-1,2] then p:=(p+modd-a[i,2]) mod modd;  end; ans:=(ans*p) mod modd; ans:=(ans*power(sum,m-t)) mod modd; writeln(ans);end.
原创粉丝点击