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