UVA - 11916 Emoogle Grid(大步小步算法)

 Emoogle Grid UVA - 11916 

因为个else改了一夜,我真是个憨憨

题意:有M*N个小方格,K种颜色,B个小方格是被打碎的,然后规定除了被打碎的小方格,其他小方格都必须涂一种颜色,并且相邻上下两行不能是同一种颜色,现在给出你对1e8+7取模后的方案数R,还有N,K,B个(x,y)坐标,求最小满足要求的M。

首先最小的M肯定是大于等于被打碎的里最大的x(没有打碎的就是1),我们先不管打碎的小方格,如果全是完好的,那么根据题意第一行的可以任意涂K种颜色,然后下面受到上面的限制就都是K-1种,也就是R=KN*(K-1)(M-1)*N

然后设q1是K的指数,q2是K-1的指数,我们考虑被打碎的小方格,如果它是第一行的,那么q1--,如果它不是最后一行的并且它下面那个小方格没被打碎,q1++,那么q2=M*N-B-q1,我们计算此时答案是不是等于R了,是的话当前的M就是答案。

而如果不是的话,那就得继续增大行数M,此时最后一行如果有打碎的小方块,那么下一行也会被影响,所以先加一行,M++,并且设最后一行打碎的小方块数目为numc,那么q1+=numc,q2+=N-numc,计算此时的答案ans,是不是等于R,如果等于答案就是M.

而如果不是的话,接下来在怎么增大M,ans都是增大(K-1)N倍,也就是解ans*(K-1)N*MMΞR (mod 1e8+7),那很明显这就是高次同余方程,拔山盖世走起,解出MM,答案就是M+MM

 1 #include<cstdio>
 2 #include<map>
 3 #include<cmath>
 4 #include<algorithm>
 5 using namespace std;
 6 typedef long long ll;
 7 const int N=511;
 8 const ll md=1e8+7;
 9 struct Node{
10     ll x,y;
11     bool operator<(const Node &n1)const{
12         return y==n1.y ? x<n1.x : y<n1.y;
13     }
14 }blo[N];
15 map<ll,ll> mmp;
16 ll rr,cc,col;
17 ll poww(ll a,ll b){
18     ll ans=1;
19     while(b){
20         if(b&1){
21             ans*=a;
22             if(ans>=md) ans%=md;
23         }
24         a*=a;
25         if(a>=md) a%=md;
26         b>>=1;
27     }
28     return  ans;
29 }
30 ll solve1(int nb,ll ans){
31     ll q1=cc,q2,numc=0,res;
32     sort(blo,blo+nb);
33     for(int i=0;i<nb;i++){
34         if(blo[i].x==1) q1--;
35         if(blo[i].x==rr) numc++;
36         if(blo[i].x!=rr){
37             if(i+1<nb&&blo[i+1].y==blo[i].y&&blo[i+1].x==blo[i].x+1) continue;
38             q1++;
39         }
40     }
41     q2=rr*cc-nb-q1;
42     res=poww(col,q1)*poww(col-1,q2)%md;
43     if(res==ans) return res;
44     rr++;q1+=numc;q2+=cc-numc;
45     res=poww(col,q1)%md*poww(col-1,q2)%md;
46     return res;
47 }
48 ll bsgs(ll a,ll b,ll c,ll d){
49     int sqc=ceil(sqrt(1.0*c));
50     ll aa=1,ac=1,ab;
51     mmp.clear();
52     for(int i=0;i<sqc;i++){
53         ab=aa*b;
54         if(ab>=c) ab%=c;
55         mmp[ab]=i;
56         aa*=a;
57         if(aa>=c) aa%=c;
58     }
59     for(int i=1;i<=sqc;i++){
60         ac*=aa;
61         if(ac>=c) ac%=c;
62         ab=ac*d;
63         if(ab>=c) ab%=c; 
64         if(mmp.count(ab)) return 1ll*i*sqc-mmp[ab];
65     }
66     return -1;
67 }
68 int main(){
69     int t=1,T,nb;
70     ll ans,ans1;
71     scanf("%d",&T);
72     while(t<=T){
73         rr=1;
74         scanf("%lld%lld%d%lld",&cc,&col,&nb,&ans);
75         for(int i=0;i<nb;i++){
76             scanf("%lld%lld",&blo[i].x,&blo[i].y);
77             rr=max(rr,blo[i].x);
78         }
79         printf("Case %d: ",t++);
80         ans1=solve1(nb,ans);
81         if(ans1==ans) printf("%lld\n",rr);
82         else printf("%lld\n",rr+bsgs(poww(col-1,cc),ans,md,ans1));
83     }
84     return 0;
85 }
知识兔
计算机