【BZOJ2751】【HAOI2012】容易题(easy) 快速幂快速乘

链接:

#include <stdio.h>
int main()
{
    puts("转载请注明出处[vmurder]谢谢");
    puts("网址:blog.csdn.net/vmurder/article/details/44684583");
}

题解:

询问只有10万个,所以有相同性质的连一块的点很多。
所以我们把 109 点分成最多 2105 块。然后就随便乱搞了。

分成 2105 块的过程是先把点排个序,然后就对每个点暴力往下删了。
然后分完了以后就是把所有的点的选择个数 x 乘起来就行了。长度为y那就乘 xy

然后可能会爆,所以需要快速乘,请见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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值