问题描述
为了使得大家高兴,小Q特意出个自认为的简单题(easy)来满足大家,这道简单题是描述如下:有一个数列A已知对于所有的A[i]都是1~n的自然数,并且知道对于一些A[i]不能取哪些值,我们定义一个数列的积为该数列所有元素的乘积,要求你求出所有可能的数列的积的和 mod 1000000007的值,是不是很简单呢?呵呵!
输入格式
第一行三个整数n,m,k分别表示数列元素的取值范围,数列元素个数,以及已知的限制条数。接下来k行,每行两个正整数x,y表示A[x]的值不能是y。
输出格式
一行一个整数表示所有可能的数列的积的和对1000000007取模后的结果。如果一个合法的数列都没有,答案输出0。
样例输入
3 4 5
1 11 1
2 2
2 3
4 3
样例输出
90
题解:
讨论一种简单情况:设n=3,A[1]=1,2 A[2]=1,2,3 A[3]=2,3
可以推出结论:
ANS=∑A[1] * ∑A[2] *......* ∑A[m]
∑A[i]表示所有A[i]能取得数字总和
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#define maxn 100005
#define ll long long
using namespace std;
const ll mod=1000000007;
ll n,m,k;
ll qans,hans=1,one,cnt=1;
struct rule
{
int num,del;
}a[maxn];
ll mont(ll a,ll b)
{
int res=1;
a%=mod;
while(b>0)
{
if(b&1)
{
res=(long long)(res*a)%mod;
}
b=(long long)b>>1;
a=(long long)(a*a)%mod;
}
return res;
}
bool cmp(rule a,rule b)
{
if(a.num==b.num)
{
return a.del<b.del;
}
return a.num<b.num;
}
int main()
{
scanf("%lld %lld %lld",&n,&m,&k);
one=(1+n)*n/2;
for(int i=1;i<=k;i++)
{
scanf("%d %d",&a[i].num,&a[i].del);
}
sort(a+1,a+k+1,cmp);
rule tmp;
tmp.num=a[1].num;
tmp.del=a[1].del;
one-=tmp.del;
for(int i=2;i<=k;i++)
{
if(a[i].num==tmp.num&&a[i].del==tmp.del)
{
continue;
}
else if(a[i].num==tmp.num&&a[i].del!=tmp.del)
{
one-=a[i].del;
tmp.del=a[i].del;
}
else if(a[i].num!=tmp.num)
{
hans=((hans%mod)*(one%mod))%mod;
one=(1+n)*n/2-a[i].del;
tmp.num=a[i].num;
tmp.del=a[i].del;
cnt++;
}
}
hans=((hans%mod)*(one%mod))%mod;
one=(1+n)*n/2;
qans=mont(one,m-cnt);
printf("%lld",((qans%mod)*(hans%mod))%mod);
}