• UVA 11916 Emoogle Grid 离散对数 大步小步算法


    LRJ白书上的题

    #include <stdio.h>
    #include <iostream>
    #include <vector>
    #include <math.h>
    #include <set>
    #include <map>
    #include <queue>
    #include <algorithm>
    #include <string.h>
    #include <string>
    using namespace std;
    typedef long long LL;
    const LL mod=1e8+7;
    const int N=505;
    
    LL n,m,k,b,r,x[N],y[N];
    set<pair<LL,LL> >bset;
    void exgcd(LL a,LL b,LL& d,LL &x,LL &y){
        if(!b){d=a;x=1;y=0;}
        else {exgcd(b,a%b,d,y,x);y-=x*(a/b);}
    }
    LL pow_mod(LL a,LL p){
        LL ans=1;
        while(p){
            if(p&1)ans=(ans*a)%mod;
            p/=2;
            a=(a*a)%mod;
        }
        return ans;
    }
    LL inv(LL a){
        LL d,x,y;
        exgcd(a,mod,d,x,y);
        return d==1?(x+mod)%mod:-1;
    }
    LL log_mod(LL a,LL b){
        LL tmp,v,e=1;
        tmp=(LL)sqrt(mod+0.5);
        v=inv(pow_mod(a,tmp));
        map<LL,LL>mp;
        mp.clear();
        mp[1]=0;
        for(LL i=1;i<tmp;++i){
            e=(e*a)%mod;
            if(!mp.count(e))mp[e]=i;
        }
        for(LL i=0;i<tmp;++i){
            if(mp.count(b))return i*tmp+mp[b];
            b=(b*v)%mod;
        }
        return -1;
    }
    LL count(){
        LL c=0;
        for(LL i=0;i<b;++i)
         if(x[i]!=m&&!bset.count(make_pair(x[i]+1,y[i])))++c;
        c+=n;
        for(LL i=0;i<b;++i)if(x[i]==1)--c;
        return pow_mod(k,c)*pow_mod((k-1),n*m-b-c)%mod;
    }
    LL solve(){
        LL cnt=count();
        if(cnt==r)return m;
        LL c=0;
        for(LL i=0;i<b;++i)if(x[i]==m)++c;
        ++m;
        cnt=(cnt*pow_mod(k,c))%mod;
        cnt=(cnt*pow_mod(k-1,n-c))%mod;
        if(cnt==r)return m;
        return log_mod(pow_mod(k-1,n),(r*inv(cnt))%mod)+m;
    }
    int main()
    {
        int T;
        scanf("%d",&T);
        for(int t=1;t<=T;++t){
            scanf("%lld%lld%lld%lld",&n,&k,&b,&r);
            bset.clear();
            m=1;
            for(LL i=0;i<b;++i){
                scanf("%lld%lld",&x[i],&y[i]);
                m=max(m,x[i]);
                bset.insert(make_pair(x[i],y[i]));
            }
            printf("Case %d: %lld
    ",t,solve());
        }
        return 0;
    }
    View Code
  • 相关阅读:
    最小路径
    零钱兑换
    硬币
    三步问题
    区域和检索
    除数博弈
    URI和URL的辨别
    交叉编译OpenMP
    牛客挑战赛44D-数列的和
    CF1408H. Rainbow Triples
  • 原文地址:https://www.cnblogs.com/shuguangzw/p/5397263.html
Copyright © 2020-2023  润新知