bzoj 2751: [HAOI2012]容易题(easy)

Description

为了使得大家高兴,小Q特意出个自认为的简单题(easy)来满足大家,这道简单题是描述如下:
有一个数列A已知对于所有的A[i]都是1~n的自然数,并且知道对于一些A[i]不能取哪些值,我们定义一个数列的积为该数列所有元素的乘积,要求你求出所有可能的数列的积的和 mod 1000000007的值,是不是很简单呢?呵呵!

solution

容易发现,我们要求的东西就是 $$(P11+P12+P13...)(P21+P22+P23...)(P31+P32+P33...)$$
对应样例中的每一项,对于有限制的部分我们暴力算,没有限制的部分就用快速幂算一下即可

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#define RG register
#define il inline
#define iter iterator
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
const int mod=1000000007;
const int N=100005;
ll n,m,k,p[N],q[N];
struct node{
   ll x,y;
   bool operator <(const node &pr)const{
      if(x!=pr.x)return x<pr.x;
      return y<pr.y;
   }
}a[N];
il ll qm(ll x,ll k){
   ll sum=1;
   while(k){
      if(k&1)sum*=x,sum%=mod;
      x*=x;x%=mod;k>>=1;
   }
   return sum;
}
void work()
{
   cin>>n>>m>>k;
   for(int i=1;i<=k;i++)
      scanf("%lld%lld",&a[i].x,&a[i].y);
   sort(a+1,a+k+1);
   ll sum=0,mul,ans=1;
   for(int i=1;i<=k;i++){
      int j=i;
      while(j<k && a[j+1].x==a[i].x)j++;
      mul=n*(n+1)>>1;
      mul-=a[i].y;
      for(int g=i+1;g<=j;g++)
         if(a[g].y!=a[g-1].y)mul-=a[g].y;
      ans*=mul%mod;ans%=mod;
      i=j;sum++;
   }
   mul=n*(n+1)>>1;mul%=mod;
   ll ret=qm(mul,m-sum);
   ans*=ret;ans%=mod;
   printf("%lld\n",ans);
}

int main()
{
	work();
	return 0;
}

posted @ 2017-11-01 22:27  Hxymmm  阅读(159)  评论(0编辑  收藏  举报