[离散对数] uva 11916 Emoogle Grid

来源:互联网 发布:w3cschool php教程 编辑:程序博客网 时间:2024/05/21 18:49

题意:

在一个M*N的矩阵内涂K种颜色。

其中有B个格子不能涂色,并且每个单元格不能和上面的那个单元格颜色一样。

已知N和总共的结果R,求最少满足的行M。

数据都对100,000,007.取模。

思路:

由于输入的不能涂色的点的X坐标一定在M以内。所以就记录一下maxX

把整个矩阵分成3个部分。

第一个部分是maxX*N.这部分的答案可以算出来看是否满足。

第二个部分是(maxX+1)*N.这个部分都是多了一行,为了去掉有些格子不能填带来的影响。

第三个部分就是M*N了,后面的(M-maxX-1)行每个格子填的颜色都是只有K-1种。

这时候设前面的答案为ans,设M-maxX-1=T

则  ans*(K-1)^(T*N) = R (mod 100000007)

这时候其实就需要求一个 A^X=B (mod M) 时的X

需要用一个枚举的方法。

代码:

#include"cstdlib"#include"cstdio"#include"cstring"#include"cmath"#include"queue"#include"algorithm"#include"iostream"#include"map"#define ll long longusing namespace std;int mark[502][502];map<int,int>id;ll mod=100000007;int n,k,b,idcnt,maxx,maxcnt;ll r;ll power(ll a,ll b){    ll ans=1;    while(b)    {        if(b&1) ans=(ans*a)%mod;        a=(a*a)%mod;        b/=2;    }    return ans%mod;}ll inv(ll x){    return power(x,mod-2);}ll log_mod(ll a,ll b){    ll m,v,e=1,i;    m=(ll)sqrt(mod+0.5);    v=inv(power(a,m));    map<ll,ll>x;    x.clear();    x[1]=0;    for(i=1;i<m;i++)    {        e=e*a;        if(e>=mod) e%=mod;        if(x[e]==0) x[e]=i;    }    for(i=0;i<m;i++)    {        if(x[b])return i*m+x[b];        b=b*v;        if(b>=mod) b%=mod;    }    return -1;}int solve(){    //1~maxx    ll ans=1;    if(maxx!=0)    {        for(int i=1;i<=idcnt;i++)        {            int cur=0;            mark[i][++mark[i][0]]=maxx+1;            for(int j=1;j<=mark[i][0];j++)            {                int sum=mark[i][j]-cur-1;                cur=mark[i][j];                if(sum==0) continue;                ans*=k;                if(ans>=mod) ans%=mod;                ans*=power(k-1,sum-1);                if(ans>=mod) ans%=mod;            }        }        ans*=power(k,n-idcnt);        if(ans>=mod) ans%=mod;        ans*=power(k-1,(maxx-1LL)*(n-idcnt));        if(ans>=mod) ans%=mod;        if(ans==r) return maxx;    }    //maxx+1    ans*=power(k,maxcnt);    if(ans>=mod) ans%=mod;    ans*=power(k-1,n-maxcnt);    if(ans>=mod) ans%=mod;    if(ans==r) return maxx+1;    ll tep=inv(ans);    ll A,B;    B=(tep*r)%mod;    A=power(k-1,n);    return log_mod(A,B)+maxx+1;}int main(){    int t,cas=1;    cin>>t;    while(t--)    {        scanf("%d%d%d%lld",&n,&k,&b,&r);        memset(mark,0,sizeof(mark));        id.clear();        idcnt=0;        maxx=0;        maxcnt=n;        for(int i=0;i<b;i++)        {            int x,y;            scanf("%d%d",&x,&y);            if(id[y]==0) id[y]=++idcnt;            mark[id[y]][++mark[id[y]][0]]=x;            if(x>maxx)            {                maxx=x;                maxcnt=1;            }            else if(x==maxx) maxcnt++;        }        printf("Case %d: %d\n",cas++,solve());    }    return 0;}


0 0
原创粉丝点击