UVA - 11916 Emoogle Grid (组合计数+离散对数)

假如有这样一道题目:要给一个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\n",solve());
58     }
59     return 0;
60 }

原文地址:https://www.cnblogs.com/asdfsag/p/10353716.html

时间: 2024-10-19 23:14:09

UVA - 11916 Emoogle Grid (组合计数+离散对数)的相关文章

UVA 11916 - Emoogle Grid(数论)

UVA 11916 - Emoogle Grid 题目链接 题意:一个N列的网格,有B个格子可以不涂色,其他格子各涂一种颜色,现在一共有k种颜色,要求同一列格子颜色不能相同,问总方案数 MOD 100000007答案等于R时最小的M是多少. 思路:先把格子分为两部分,有不涂色的一部分,没有的一部分,然后计算出有的情况数,之后如果每多一行,每个格子上能涂颜色必然是k - 1种,也就是每多一行多(k - 1)^n总方案,所以也就是求 前一部分情况 * ((k - 1)^n)^x % MOD = R时

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

题目连接:uva 11916 - Emoogle Grid 题目大意:有一问题,在M行N列的网格上涂K种颜色,其中有B个格子不用涂色,其它每个格子涂一种颜色,同一列的上下两个相邻的格子不能涂相同的颜色.给出M,N,K和B个格子的位置,求出总方案数模掉1e8+7的结果R.现在已知R,求最小的M. 解题思路:有确定不用涂色格子的区域作为不变部分,总数通过计算为tmp,外加可变部分的第一行,方案数为cnt,可变部分除第一行外,每加一行都将总数乘以(K?1)N,既有 cnt?PM=Rmod(1e8+7)

UVA - 11916 Emoogle Grid (离散对数取模)

You have to color an M x N (1M, N108) two dimensional grid. You will be provided K (2K108) different colors to do so. You will also be provided a list of B (0B500)list of blocked cells of this grid. You cannot color those blocked cells. A cell can be

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

uva 11916 Emoogle Grid

题意:用K种颜色给一个N*M的格子涂色.其中有B个格子是不能涂色的.涂色时满足同一列上下紧邻的两个格子的颜色不同.所有的涂色方案模100000007后为R.现在给出M.K.B.R,求一个最小的N,满足题意. 思路:分成两个部分.设给出的B个不能涂的格子的最大行坐标为m. 首先,我们能计算出前m行的方案数cnt,若cnt=r,则m就是答案.每增加一行,就会增加(K-1)^m种方法,接着令p=(K-1)^M,我们能计算出前m+1行的方案数cnt,若cnt=r 则答案为 m+1.否则,设下面还需要t行

uva 12508 - Triangles in the Grid(几何+计数)

题目链接:uva 12508 - Triangles in the Grid 题目大意:给出n,m,A和B,要求计算在(n+1)?(m+1)的矩阵上,可以找出多少个三角形,面积在AB之间. 解题思路:首先枚举矩阵,然后计算有多少个三角形以该矩阵为外接矩阵,并且要满足体积在AB之间.然后对于每个矩阵,要确定在大的范围内可以确定几个. 枚举矩阵的内接三角形可以分为三类: 1.三角型的两点在一条矩阵边上的顶点,另一点在该边的对边上(不包括顶点) 2.以对角线为三角形的一边 这样可以枚举x,然后求出l和

[uva11916] Emoogle Grid (离散对数)

转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud  Emoogle Grid  You have to color an MxN ( 1M, N108) two dimensional grid. You will be provided K ( 2K108) different colors to do so. You will also be provided a list of B ( 0B500) list of blo

Yue Fei&#39;s Battle(组合计数递推)

//求一个直径为 k 的树有多少种形态,每个点的度不超过 3 // 非常完美的分析,学到了,就是要细细推,并且写的时候要细心 还有除法取模需要用逆元 #include <iostream> #include <stdio.h> #include <string.h> #include <math.h> #include <stdlib.h> using namespace std; #define MOD 1000000007 #define L

uva 12163 - Addition-Subtraction Game(组合游戏)

题目链接:uva 12163 - Addition-Subtraction Game 题目大意:两个人进行游戏,对于每一局有一个无向图,给出无向图,每个节点有个K值,两人轮流操作,每次可以选中国一个含有石子的节点,将该节点的一个石子拿掉,然后选择K个有边连接的节点加上一个石子(节点可以重复选择),每个节点的子节点不会超过15个.不能操作的人视为失败.每局有n轮,给定每轮中每个节点上石子的初始值,问先手胜利还是失败. 解题思路:有向图上移动石子的组合游戏,对于没有子节点的节点SG值为0,然后对于每