当前位置: 代码迷 >> 综合 >> 【HAOI2012】bzoj2751 容易题
  详细解决方案

【HAOI2012】bzoj2751 容易题

热度:94   发布时间:2024-01-13 11:29:15.0

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。

根据乘法分配律可以知道,答案就是把每一个位置所有可行的值的和乘起来。有限制的单独算,没有限制的快速幂。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;
const int mod=1000000007;
struct ban
{int p,x;bool operator < (const ban & bb) const{return p<bb.p||(p==bb.p&&x<bb.x);}
}a[100010];
int pow(int x,int p)
{int ret=1;while (p){if (p&1) ret=(LL)ret*x%mod;x=(LL)x*x%mod;p>>=1;}return ret;
}
int main()
{int i,j,k,m,n,p,q,x,y,z,cnt=0,sum,ans=1,now=1;scanf("%d%d%d",&n,&m,&k);sum=(LL)n*(n+1)%mod*pow(2,mod-2)%mod;for (i=1;i<=k;i++)scanf("%d%d",&a[i].p,&a[i].x);sort(a+1,a+k+1);a[0]=(ban){-1,-1};a[k+1]=(ban){-2,-2};for (i=1;i<=k+1;i++){if (a[i].p!=a[i-1].p){ans=(LL)ans*now%mod;cnt++;now=sum;}if (a[i].p!=a[i-1].p||a[i].x!=a[i-1].x) now=((now-a[i].x)%mod+mod)%mod;}printf("%d\n",(LL)ans*pow(sum,m-cnt+1)%mod);
}