看到这个题目名字总感觉它在嘲讽我做不出来
题目描述:有m个数组成数列,数列中的每个数都在1~n范围内,求数列的每种情况内每个位置上的每个数乘起来的和。
思路:我们可以先假设没有任何限制,那么我们的答案就是(n(n+1)/2)m,为什么那,下面给出计算过程(以n=2,m=3为例):
由于本题带有限制,则我们可以先只处理没有限制的数位,之后再和带有限制的数相加就行了,即(n(n+1)/2)m-num(num为有限制的数的个数)再加上有限制的数算出的结果.
还有就是注意要用快速幂优化,不然会超时,注意去重。另外,写取模时最好记得加括号,不然算式的计算方式可能会发生改变,失去取模意义。
代码:
1 #include<cstdio> 2 #include<algorithm> 3 #include<algorithm> 4 #include<vector> 5 #include<map> 6 const int N=5e6+10; 7 const int Mod=1000000007; 8 typedef long long ll; 9 using namespace std; 10 ll num[N]; 11 map<ll,ll>cal; 12 map<pair<ll,ll>,bool>mp;//去重 13 ll n,m,k; 14 ll pow(ll a,ll t){//快速幂 15 a%=Mod; 16 ll ans=1; 17 while(t){ 18 if(t&1) ans=(ans*a)%Mod; 19 t>>=1; 20 a=(a*a)%Mod; 21 } 22 return ans; 23 } 24 int main(){ 25 scanf("%lld%lld%lld",&n,&m,&k); 26 for(ll i=1;i<=k;++i){ 27 ll x,y; 28 scanf("%lld%lld",&x,&y); 29 if(!cal[x]) num[++num[0]]=x; 30 if(mp[make_pair(x,y)]) continue; 31 mp[make_pair(x,y)]=1; 32 cal[x]+=y;//用于计算有限制的答案 33 } 34 ll ans=1,sum=n*(n+1)/2; 35 for(ll i=1;i<=num[0];++i){//计算有限制的答案 36 ans=((ans%Mod)*((sum-cal[num[i]])%Mod))%Mod; 37 } 38 printf("%lld ",(ans%Mod*pow(sum,m-num[0])%Mod)%Mod);//加和 39 return 0; 40 }