zoukankan      html  css  js  c++  java
  • UVA

    假如有这样一道题目:要给一个M行N列的网格涂上K种颜色,其中有B个格子不用涂色,其他每个格子涂一种颜色,同一列中的上下两个相邻格子不能涂相同颜色。给出M,N,K和B个格子的位置,求出涂色方案总数除以1e8+7的结果R。

    本题的任务和这个相反:已知N,K,R和B个格子的位置,求最小可能的M。

    蓝书(大白)上的例题,设xm为不能涂色的格子的最大x值,则分三种情况讨论:M=xm,M=xm+1,M>xm+1。前两种用组合公式直接算,第三种可设前xm+1行的格子涂色方法有n种,由于每增加一行,总涂色方案数增加p=(k-1)^N,于是有n*p^(M-xm-1)=R,用BSGS算法求出M-xm-1的值即可得到答案。

    中间有一个连乘少取了一次模爆了longlong,差点debug到自闭..

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 typedef long long ll;
     5 const ll N=500+10;
     6 const ll mod=1e8+7;
     7 struct P {
     8     ll x,y;
     9     bool operator<(const P& b)const {return x!=b.x?x<b.x:y<b.y;}
    10 };
    11 ll n,k,b,r,ka;
    12 ll x[N],y[N],xm,all;
    13 set<P> st;
    14 
    15 ll Pow(ll a,ll b) {
    16     ll ret=1;
    17     for(; b; b>>=1,a=a*a%mod)if(b&1)ret=ret*a%mod;
    18     return ret;
    19 }
    20 ll inv(ll a) {return Pow(a,mod-2);}
    21 ll Log(ll a,ll b) {
    22     ll m=sqrt(mod+0.5),v=inv(Pow(a,m));
    23     map<ll,ll> mp;
    24     for(ll i=0,e=1; i<m; ++i,e=e*a%mod)if(!mp.count(e))mp[e]=i;
    25     for(ll i=0; i<m; ++i,b=b*v%mod)if(mp.count(b))return i*m+mp[b];
    26     return -1;
    27 }
    28 
    29 ll solve() {
    30     ll ans=Pow(k,all)*Pow(k-1,n*xm-all-b)%mod;
    31     if(ans==r)return xm;
    32     ll cnt=0;
    33     for(ll i=0; i<b; ++i)if(x[i]==xm)++cnt;
    34     ans=ans*Pow(k,cnt)%mod*Pow(k-1,n-cnt)%mod;
    35     if(ans==r)return xm+1;
    36     return xm+1+Log(Pow(k-1,n),r*inv(ans)%mod);
    37 }
    38 
    39 int main() {
    40     ll T;
    41     scanf("%lld",&T);
    42     while(T--) {
    43         printf("Case %lld: ",++ka);
    44         xm=1;
    45         st.clear();
    46         scanf("%lld%lld%lld%lld",&n,&k,&b,&r);
    47         all=n;
    48         for(ll i=0; i<b; ++i) {
    49             scanf("%lld%lld",&x[i],&y[i]);
    50             xm=max(xm,x[i]);
    51             st.insert({x[i],y[i]});
    52             if(x[i]==1)all--;
    53         }
    54         for(ll i=0; i<b; ++i) {
    55             if(x[i]!=xm&&!st.count({x[i]+1,y[i]}))all++;
    56         }
    57         printf("%lld
    ",solve());
    58     }
    59     return 0;
    60 }
  • 相关阅读:
    hdu 4324(dfs)
    hdu 2376(求树上任意两点之间距离之和的平均值)
    hdu 3665(最短路)
    hdu 4463(最小生成树变形)
    hdu 2242(边双连通分量)
    hdu 2682(最小生成树)
    hdu 2444(二分图的判断以及求最大匹配)
    陶哲轩实分析命题6.4.12
    陶哲轩实分析习题8.3.4
    CantorBernsteinSchroeder定理的证明
  • 原文地址:https://www.cnblogs.com/asdfsag/p/10353716.html
Copyright © 2011-2022 走看看