发现蒟蒻只会刷这种容易题了囧
2751: [HAOI2012]容易题(easy)
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 882 Solved: 381
[ Submit][ Status]
Description
为了使得大家高兴,小Q特意出个自认为的简单题(easy)来满足大家,这道简单题是描述如下:
有一个数列A已知对于所有的A[i]都是1~n的自然数,并且知道对于一些A[i]不能取哪些值,我们定义一个数列的积为该数列所有元素的乘积,要求你求出所有可能的数列的积的和 mod 1000000007的值,是不是很简单呢?呵呵!
Input
第一行三个整数n,m,k分别表示数列元素的取值范围,数列元素个数,以及已知的限制条数。
接下来k行,每行两个正整数x,y表示A[x]的值不能是y。
Output
一行一个整数表示所有可能的数列的积的和对1000000007取模后的结果。如果一个合法的数列都没有,答案输出0。
Sample Input
3 4 5
1 1
1 1
2 2
2 3
4 3
1 1
1 1
2 2
2 3
4 3
Sample Output
90
样例解释
A[1]不能取1
A[2]不能去2、3
A[4]不能取3
所以可能的数列有以下12种
数列 积
2 1 1 1 2
2 1 1 2 4
2 1 2 1 4
2 1 2 2 8
2 1 3 1 6
2 1 3 2 12
3 1 1 1 3
3 1 1 2 6
3 1 2 1 6
3 1 2 2 12
3 1 3 1 9
3 1 3 2 18
样例解释
A[1]不能取1
A[2]不能去2、3
A[4]不能取3
所以可能的数列有以下12种
数列 积
2 1 1 1 2
2 1 1 2 4
2 1 2 1 4
2 1 2 2 8
2 1 3 1 6
2 1 3 2 12
3 1 1 1 3
3 1 1 2 6
3 1 2 1 6
3 1 2 2 12
3 1 3 1 9
3 1 3 2 18
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
想不到省选里也会有这种的水平题目。。。
说好听点叫倍增,说难听点叫快速幂?NOIP T1难度?
算了算了。。
很明显它的答案就是每一位(可以取到的数的和)的乘积 [嗯请注意运算优先顺序]
发现K很小对吧。。
所以改过的不会有很多。。
所以对于没有改过的(假设有k个),就是(n(n+1))^k
有改过的就是进来先对x快排一下,然后对于每一个x都统计一下就好了,反正也不会很大。。
Code:
const shuru='easy.in';
shuchu='easy.out';
maxn=100001;
modn=1000000007;
long=10007;
var a,b:array[0..maxn] of int64;
hash:array[0..long] of boolean;
tmp,count,ans,now,step,n,m,k:int64;
i,j,l:longint;
procedure init;
begin
readln(n,m,k);
for i:=1 to k do readln(a[i],b[i]);
end;
procedure qsort(left,right:longint);
var i,j,mid:longint;
begin
i:=left; j:=right; mid:=a[(i+j) shr 1];
repeat
while a[i]<mid do inc(i);
while a[j]>mid do dec(j);
if i<=j then begin
tmp:=a[i]; a[i]:=a[j]; a[j]:=tmp;
tmp:=b[i]; b[i]:=b[j]; b[j]:=tmp;
inc(i); dec(j);
end;
until i>j;
if j>left then qsort(left,j);
if i<right then qsort(i,right);
end;
procedure main;
begin
init;
step:=n*(n+1) div 2;
step:=step mod modn;
qsort(1,k);
i:=1;ans:=1;
while (i<=k) do
begin
j:=i;
now:=step;
fillchar(hash,sizeof(hash),false);
while a[j+1]=a[j] do inc(j);
for l:=i to j do begin
if hash[b[l] mod long] then continue;
hash[b[l] mod long]:=true;
now:=now-b[l];
end;
inc(count);
ans:=(ans*now) mod modn;
i:=j+1;
end;
m:=m-count;
while (m>0) do
begin
if (m and 1=1) then ans:=ans*step mod modn;
m:=m shr 1;
step:=step*step mod modn;
end;
writeln(((ans mod modn)+modn) mod modn);
end;
begin
main;
end.