zoukankan      html  css  js  c++  java
  • 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
Copyright © 2011-2022 走看看