[HAOI2012] 容易題

題目

首先,原題題目就叫這個,不是我諷刺這個題簡單……
原題地址c++

解說

我們先假設我一個限制都沒有,那麼每一個數均可以取\(1~n\)之間的任何一個整數,在本身的腦海裏提一遍公因數就會發現這時答案爲\((1+2+ \dots +n)^m\),再用上求和公式變爲\((\frac{n(n+1)}{2})^m\)
那麼如今咱們加上限制條件,每加上一個限制就少一個選擇,那麼咱們就把這個限制數從這個乘數裏剔除便可,即原來是\(1+2+ \dots +n\),如今變爲\(1+2+ \dots +n-limit1-limit2 \dots\),也就是\((\frac{n(n+1)}{2})^m-limit1-limit2 \dots\)。而沒有受到限制的數照乘不誤,即如有\(js\)個有限制的數那麼這些沒限制的數乘起來就是\((\frac{n(n+1)}{2})^{m-js}\)。最後結果把有限制的沒限制的乘一塊兒便可。
幾點提醒:
1.數太大了,能取模的地方都取模。
2.用快速冪優化。
3.樣例就能看出來可能有重複限制,記得去重。優化

代碼

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1000000007;
const int maxn=1e5+3;
map<pair<ll,ll>,bool> inf;
map<ll,ll> sum;
ll n,m,k,js,num[maxn];
ll power(ll a,ll x){
	a%=mod;
	ll ans=1;
	for(;x;x>>=1,a=a*a%mod){
		if(x&1) ans=ans*a%mod;
	}
	return ans%mod;
}
ll read(){
   ll s=0,w=1;
   char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
   while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
   return s*w;
} 
int main(){
	n=read(); m=read(); k=read();
	while(k--){
		ll x,y;
		x=read(); y=read();
		if(!sum[x]) num[++js]=x;
		if(inf[make_pair(x,y)]) continue;
		inf[make_pair(x,y)]=1;
		sum[x]+=y;
	}
	ll ans=1,Max=(n+1)*n/2;
	for(ll i=1;i<=js;i++){
		ans*=(Max-sum[num[i]])%mod;
		ans%=mod;
	}
	printf("%lld",ans%mod*power(Max,m-js)%mod%mod);
	return 0;
}

幸甚至哉,歌以詠志。spa

相關文章
相關標籤/搜索