codeforces 722F - Cyclic Cipher

Posted sagitta

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了codeforces 722F - Cyclic Cipher相关的知识,希望对你有一定的参考价值。

题目链接:http://codeforces.com/problemset/problem/722/F

------------------------------------------------------------------------------

首先根据 $k <= 40$  以及 $lcm(1...40)$ 在$long long$以内

可以意识到这题可以转化为求最大合法区间使得区间内的同余方程组合法

这个可以考虑用$exgcd$来做 并且也满足区间可合并的性质

对于一段连续区间 我们枚举左端点要找到最远的合法的右端点 可以先用$ST$表预处理后倍增查找

$($注意线段树/$ST$表要进行二分的时候不要真的进行二分 这样会多一个$log$ 要利用已经分割好的区间$)$

最后复杂度是$O(n * logn * exgcd$复杂度$)$

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 const int N = 1e5 + 10, E = 2e5 + 10;
  4 int len[N], firste[N], nexte[E], v[E], w[E];
  5 int n, lim, e, ans, m;
  6 void build(int x, int y, int z)
  7 {
  8     nexte[++e] = firste[x];
  9     firste[x] = e;
 10     v[e] = y;
 11     w[e] = z;
 12 }
 13 void exgcd(long long a,long long b,long long &d, long long &x, long long &y)
 14 {
 15     if(!b)
 16     {
 17         x = 1;
 18         y = 0;
 19         d = a;
 20     }
 21     else
 22     {
 23         exgcd(b, a % b, d, y, x);
 24         y -= x * (a / b);
 25     }
 26 }
 27 long long a[17][N], b[17][N];
 28 long long mul(long long aa, long long bb, long long mod)
 29 {
 30     return (aa * bb - (long long)(aa / (long double) mod * bb + 1e-3) * mod + mod) % mod ;
 31 }
 32 void solve(long long m1, long long b1, long long m2, long long b2, long long &m0, long long &b0)
 33 {
 34     if(m1 == -1 || m2 == -1)
 35     {
 36         m0 = b0 = -1;
 37         return;
 38     }
 39     long long d, x, y;
 40     exgcd(m1, m2, d, x, y);
 41     if((b2 - b1) % d != 0)
 42         m0 = b0 = -1;
 43     else
 44     {
 45         long long t = m2 / d;
 46         //x = (x % t * ((b2 - b1) / d % t) % t + t) % t;
 47         x = (mul(x, (b2 - b1) / d, t) + t) % t;
 48         m0 = m1 * (m2 / d);
 49         b0 = m1 * x + b1;
 50     }
 51 }
 52 int main()
 53 {
 54     scanf("%d%d", &n, &lim);
 55     int x;
 56     for(int i = 1; i <= n; ++i)
 57     {
 58         scanf("%d", &len[i]);
 59         for(int j = 0; j < len[i]; ++j)
 60         {
 61             scanf("%d", &x);
 62             build(x, i, j);
 63         }
 64     }
 65     int last;
 66     for(int u = 1; u <= lim; ++u)
 67     {
 68         ans = m = last = 0;
 69         for(int p = firste[u]; ; p = nexte[p])
 70         {
 71             if(p && (!m || v[p] == last - 1))
 72             {
 73                 ++m;
 74                 a[0][m] = len[v[p]];
 75                 b[0][m] = w[p];
 76                 last = v[p];
 77                 continue;
 78             }
 79             else
 80             {
 81                 if(m > ans)
 82                 {
 83                     int top = 0;
 84                     for(int i = 1; (1 << i) <= m; ++i)
 85                     {
 86                         top = i;
 87                         for(int j = 1; j + (1 << i) - 1 <= m; ++j)
 88                             solve(a[i - 1][j], b[i - 1][j], a[i - 1][j + (1 << (i - 1))], 
 89                             b[i - 1][j + (1 << (i - 1))], a[i][j], b[i][j]);
 90                     }
 91                     for(int j = 1; m - j + 1 > ans; ++j)
 92                     {
 93                         int k = j + 1;
 94                         long long nowa = a[0][j], nowb = b[0][j], tmpa, tmpb;
 95                         for(int i = top; i >= 0; --i)
 96                             if(k + (1 << i) - 1 <= m)
 97                             {
 98                                 solve(nowa, nowb, a[i][k], b[i][k], tmpa, tmpb);
 99                                 if(tmpa != -1)
100                                 {
101                                     k += (1 << i);
102                                     nowa = tmpa;
103                                     nowb = tmpb;
104                                 }
105                             }
106                         ans = max(ans, k - j);
107                     }
108                 }
109                 if(!p)
110                     break;
111                 m = 1;
112                 a[0][m] = len[v[p]];
113                 b[0][m] = w[p];
114                 last = v[p];
115             }
116         }
117         printf("%d\n", ans);
118     }
119     return 0;
120 }

 

以上是关于codeforces 722F - Cyclic Cipher的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces 754E:Dasha and cyclic table

Codeforce 977E Cyclic Components

codeforces E. Cyclic Components

CodeForces 709C Letters Cyclic Shift

Codeforces Problem 708A Letters Cyclic Shift

CodeForces 709C Letters Cyclic Shift (水题)