UVa 11916 (离散对数) Emoogle Grid

因为题目要求同列相邻两格不同色,所以列与列之间不影响,可以逐列染色。

如果一个格子的上面相邻的格子,已经被染色则染这个格子的时候,共有k-1中选择。

反过来,如果一个格子位于第一列,或者上面相邻的格子是不能被染色的格子,则共有k中选择。

虽然,矩阵的行数不定,但至少为所有不能被染色格子行标的最大值m。

分别检验一下染m行和m+1行的方案数(mod 100000007)是否为r

否则的话,后面每染一行方案数都会乘p = (k-1)n,假设前面计算出来的m+1行方案数为cnt

下面的任务就是求解 px * cnt = r (mod MOD),两边乘cnt的逆,得 px = r * cnt-1 (mod MOD)

最后加上前面的m+1行,答案为x + m + 1

最后吐槽一下我认为的坑点=_=,看到那个模想当然地以为是1e9+7,但是最后一个样例调了好久没过,后来才发现题中给的模是1e8+7

 1 #include <cstdio>
 2 #include <map>
 3 #include <set>
 4 #include <cmath>
 5 #include <algorithm>
 6 using namespace std;
 7 #define MP make_pair
 8 #define INS insert
 9 typedef long long LL;
10
11 const int MOD = 100000007;
12 const int maxb = 500 + 10;
13 int n, m, k, b, r, x[maxb], y[maxb], fir_row;
14 set<pair<int, int> > Set;
15
16 int mul_mod(int a, int b)
17 { return (LL) a * b % MOD; }
18
19 int pow_mod(int a, LL n)
20 {
21     int ans = 1, base = a;
22     while(n)
23     {
24         if(n & 1) ans = mul_mod(ans, base);
25         base = mul_mod(base, base);
26         n >>= 1;
27     }
28     return ans;
29 }
30
31 int inv(int a)
32 { return pow_mod(a, MOD - 2); }
33
34 int log_mod(int a, int b)
35 {//a^x=b (mod MOD)
36     int m, v, e = 1, i;
37     m = (int)sqrt(MOD + 0.5);
38     v = inv(pow_mod(a, m));
39     map<int, int> x;
40     x[1] = 0;
41     for(i = 1; i < m; i++)
42     {
43         e = mul_mod(e, a);
44         if(e == b) return i;
45         if(!x.count(e)) x[e] = i;
46     }
47     for(i = 0; i < m; i++)
48     {
49         if(x.count(b)) return i*m + x[b];
50         b = mul_mod(b, v);
51     }
52     return -1;
53 }
54
55 int solve()
56 {
57     int c = 0;//前m行涂k种颜色的格子个数
58     for(int i = 0; i < b; i++)
59         if(x[i] != m && !Set.count(MP(x[i] + 1, y[i]))) c++;
60     c += n - fir_row;
61     int cnt = mul_mod(pow_mod(k, c), pow_mod(k-1, (LL)m*n - b - c));
62     if(cnt == r) return m;
63
64     c = 0;//第m+1行涂k种颜色的格子个数
65     for(int i = 0; i < b; i++) if(x[i] == m) c++;
66     cnt = mul_mod(mul_mod(cnt, pow_mod(k, c)), pow_mod(k-1, n-c));
67     if(cnt == r) return m + 1;
68
69     int p = pow_mod(k-1, n);
70     int v = inv(cnt);
71     return log_mod(p, mul_mod(r, v)) + m + 1;
72 }
73
74 int main()
75 {
76     //freopen("in.txt", "r", stdin);
77
78     int T;
79     scanf("%d", &T);
80     for(int kase = 1; kase <= T; kase++)
81     {
82         scanf("%d%d%d%d", &n, &k, &b, &r);
83         Set.clear();
84         m = 1; fir_row = 0;
85         for(int i = 0; i < b; i++)
86         {
87             scanf("%d%d", &x[i], &y[i]);
88             Set.INS(MP(x[i], y[i]));
89             if(x[i] > m) m = x[i];
90             if(x[i] == 1) fir_row++;//第一行不能被涂色的个数
91         }
92         printf("Case %d: %d\n", kase, solve());
93     }
94
95     return 0;
96 }

代码君

时间: 2024-08-05 21:57:43

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)

[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

UVA - 10913Walking on a Grid(记忆化搜索)

题目:Walking on a Grid 题目大意:给出N * N的矩阵,每个格子里都有一个值,现在要求从(1,1)走到(n, n),只能往下,左,右这三个方向走,并且要求最多只能取k个负数,求这样的要求下能得到的走过格子的值之和最大. 解题思路:记忆化搜索,但是这里要四维的,因为要记录方向,为了防止走回头的路,并且取了几个负数也要记录.然后就是dfs了.状态转移方程:dp[x][y][d][k] = dp[x + dir[i][0]][y + dir[i][1]][i][k1] + G[x][

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 (组合计数+离散对数)

假如有这样一道题目:要给一个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种,由于每增加一行,总涂色方案数

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行

uva11916 Emoogle Grid (BSGS)

https://uva.onlinejudge.org/external/119/p11916.pdf 令m表示不能染色的格子的最大行号 设>m行时可以染k种颜色的格子数有ck个,恰好有m行时可以染k种颜色的格子数有ckm个 分m行.m+1行.>m+1行讨论 如果是m行:k^ckm * (k-1)^(n*m-b-ckm) = r 如果是m+1行, k^ckm * (k-1)^(n*m-b-ckm) * k^(ck-ckm) * (k-1)^(n-(ck-ckm)) = r 如果>m行,k