bzoj2751[HAOI2012]容易题(easy)

bzoj2751[HAOI2012]容易题(easy)

题意:

已知一个数列A对于所有的A[i]都是1~n的自然数,一些A[i]不能取一些值,求出所有可能的数列的积的和 mod 1000000007的值。

题解:

题目中的n≤109实际上是109……首先推个方程s[l,r]=s[l,k]*s[k+1,r](s[l,r]表示l到r的所有l≤i≤r的a[i]的可能取值的和)因此s[1,n]等于所有a[i]的可能取值的和的乘积。因此我们先求出1到n的和,对每个约束条件按i排序,将这个和减掉约束条件中的不能取的数,就是这个a[i]所有可能取值的和。将这些a[i]乘起来,剩下的没限制的a[i]用快速幂解决。

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #define ll long long
 5 #define inc(i,j,k) for(int i=j;i<=k;i++)
 6 #define mod 1000000007
 7 using namespace std;
 8 
 9 struct nd{
10     ll a,b;
11     bool operator < (const nd &c)const{
12         if(a!=c.a)return a<c.a;else return b<c.b;
13     }
14 };
15 ll power(ll a,ll b){
16     if(b==0)return 1; if(b==1)return a; ll c=power(a,b>>1)%mod;
17     if(b&1)return c*c%mod*a%mod;else return c*c%mod;
18 }
19 nd ns[200000];
20 int main(){
21     ll n,m,a1=0,a2,a3,a4; ll k; scanf("%lld%lld%lld",&n,&m,&k);
22     inc(i,1,k)scanf("%lld%lld",&ns[i].a,&ns[i].b); sort(ns+1,ns+k+1);
23     inc(i,1,k)if(i==1||ns[i].a!=ns[i-1].a)a1++; a2=n*(n+1)/2%mod; a3=a4=1;
24     inc(i,1,k)if(i==1||ns[i].a!=ns[i-1].a)a4=a4*a3%mod,a3=a2,a3=(a3-ns[i].b)>=0?(a3-ns[i].b)%mod:(a3-ns[i].b)+mod;
25     else if(ns[i].b!=ns[i-1].b)a3=(a3-ns[i].b)>=0?(a3-ns[i].b)%mod:(a3-ns[i].b)+mod;
26     a4=a4*a3%mod; a4=a4*power(a2,m-a1)%mod; printf("%lld",a4);
27 }

 

20160419

posted @ 2016-07-25 13:55  YuanZiming  阅读(243)  评论(0编辑  收藏  举报