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 }
代码君

 

posted @ 2015-03-09 06:46  AOQNRMGYXLMV  阅读(235)  评论(0编辑  收藏  举报