#include <stdio.h>
int main()
{
puts("转载请注明出处[vmurder]谢谢");
puts("网址:blog.csdn.net/vmurder/article/details/44684583");
}
询问只有10万个,所以有相同性质的连一块的点很多。
所以我们把
分成
然后分完了以后就是把所有的点的选择个数
然后可能会爆,所以需要快速乘,请见mul部分。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 201000
#define mod 1000000007
using namespace std;
struct Eli
{
long long x,y,z;
void read(){cin>>x>>y;}
Eli(long long _x=0,long long _y=0,long long _z=0):x(_x),y(_y),z(_z){}
bool operator <(const Eli &A)const
{return x==A.x?y<A.y:x<A.x;}
}eli[N],src[N];
long long n,m,p,cnt;
long long mul(long long a,long long b)
{
long long ret=0;
while(b)
{
if(b&1)ret=(ret+a)%mod;
a<<=1,a%=mod,b>>=1;
}
return ret;
}
long long power(long long a,long long b)
{
long long ret=1;
while(b)
{
if(b&1)ret=mul(ret,a);
a=mul(a,a),b>>=1;
}
return ret;
}
long long ans=0;
long long lsum[N],rsum[N];
int main()
{
int i,j,k;
cin>>n>>m>>p;
for(i=1;i<=p;i++)eli[i].read();
sort(eli+1,eli+p+1);
long long sum=n*(n+1)/2;
long long t=sum,last=1ll,r=n;
for(i=1;i<=p;i++)
{
if(eli[i].x!=last)
{
src[++cnt]=Eli(1,r%mod,t%mod);
k=eli[i].x-last;
if(k>1)src[++cnt]=Eli(k-1,n%mod,sum%mod);
last=eli[i].x,r=n-1,t=sum-eli[i].y;
}
else {
if(eli[i].y==eli[i-1].y)continue;
r--,t-=eli[i].y;
}
}
src[++cnt]=Eli(1,r%mod,t%mod);
k=m-last;
if(k)src[++cnt]=Eli(k,n%mod,sum%mod);
/* lsum[0]=rsum[cnt+1]=1ll;
for(i=1;i<=cnt;i++)
{
lsum[i]=lsum[i-1]*power(src[i].y,src[i].x)%mod;
}
for(i=cnt;i;i--)
{
rsum[i]=rsum[i+1]*power(src[i].y,src[i].x)%mod;
}
for(i=1;i<=cnt;i++)
{
ans=(ans+src[i].x*src[i].z%mod*lsum[i-1]%mod*rsum[i+1]%mod)%mod;
}*/
ans=1;
for(i=1;i<=cnt;i++)
{
ans=ans*power(src[i].z,src[i].x)%mod;
}
cout<<ans<<endl;
return 0;
}
【BZOJ2751】【HAOI2012】容易题(easy) 快速幂快速乘
原文:http://blog.csdn.net/vmurder/article/details/44684583