P2220 [HAOI2012]容易题

看到这个题目名字总感觉它在嘲讽我做不出来

题目描述:有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 }
View Code
原文地址:https://www.cnblogs.com/li-jia-hao/p/12887979.html