题目
点这里看题目。
现在有一个长度为 \(n\) 的整数序列 \(S\),\(S\) 的元素从 \(0\) 开始编号。Alice 和 Bob 在这个序列上博弈。
博弈的过程有若干轮,每一轮的过程如下:
- Alice 给出一个长度为 \(T\) 的整数序列。
- Bob 选定一个非负整数 \(x\),满足 \(0\le x<n\)。
- 对于每一个 \(0\le y<n\),令 \(S_y\gets S_y+T_{(y+x)\bmod n}\)。
如果某一轮结束后,\(S\) 中的数都是某一个给定质数 \(p\) 的倍数,则说 Alice 胜利。
你需要判断 Alice 是否可以在有限多轮内保证必胜。如果可以,还需要求出最小的 \(s\),使得在 \(s\) 轮内 Alice 可以保证必胜。
所有数据满足 \(1\le n\le 3\times 10^5,2\le p\le 200\)。
分析
很好玩的一道题,可惜被我草菅了。
问题看起来很复杂,先翻译一下。考虑一列命题 \(\{q_m\}\),其中 \(q_m\):“在 \(m\) 轮内 Alice 可以保证必胜”。则两个问题分别是:
- 是否 \(\exist m\in \mathbb N,\text{s.t. } q_m\)。
- 求出 \(\min\{m\in \mathbb N|q_m\land (\neg q_{m-1}\lor m=0)\}\)。
我们不妨先研究一下 \(q_m\) 的等价命题。考虑一些比较小的情况:
-
\(m=0\) 时,这就意味着 \(S\) 全为 \(0\)。
-
\(m=1\) 时,可以发现 \(S\) 包含的元素全部相同为一种可能的情况。利用反证法容易证明 \(q_1\Leftrightarrow\) “\(S\) 中的数全部相同”。
-
\(m=2\) 时,我们需要更清晰地描述这个问题。
不妨假设一个 \(T\),使得无论 \(x\) 取到何值,经过变换后 \(S\) 中的数都全部相同。
也即 \(\forall 0\le x<n,\forall 0\le y<n,S_y+T_{(y+x)\bmod n}\equiv S_{(y+1)\bmod n}+T_{(y+1+x)\bmod n}\pmod p\)。
也就是 \(\forall 0\le y<n,\forall 0\le x<n,S_{(y+1)\bmod n}-S_{y}\equiv T_{(y+x)\bmod n}-T_{(y+1+x)\bmod n}\pmod p\)。
由 \(x,y\) 取值的任意性,我们可以得到:\(\Delta S,\Delta T\) 各自的数全部相同。
Note.
这里的 \(\Delta\) 表示“循环差分”,也即 \((\Delta S)_x=S_{(x+1)\bmod n}-S_x\)。
根据推理过程,这是一个必要条件,其充分性也容易证明。
-
归纳一下已有的结果,我们发现 $q_m(m=0,1,2)\Leftrightarrow $“在模 \(p\) 意义下,\(\Delta^m S\) 中的数全为 \(0\)“。
推广到 \(m\in \mathbb N\),这个关系都是成立的。证明可以使用数学归纳法,限于篇幅此处略去。
现在,我们要做的就是:
- 判定是否 \(\exist m\in \mathbb N\),使得在模 \(p\) 意义下,\(\Delta^mS\) 中的数全为 \(0\)。
- 求一个最小的 \(m\in\mathbb N\),使得在模 \(p\) 意义下,\(\Delta^mS\) 中的数全为 \(0\)。
我们可以把 \(\Delta^m\) 展开来观察一下:
\[(\Delta^m S)_x=\sum_{k=0}^m\binom{m}{k}(-1)^{m-k}S_{(x+k)\bmod n} \]注意到模数很小,我们很快就想到了经典性质 \(\dbinom{p}{k}\equiv [k=0\lor k=p]\pmod p\)。此结论可来自于 Lucas 定理,所以容易推广得到 \(\forall r\in \mathbb N^*,\dbinom{p^r}{k}\equiv[k=0\lor k=p^r]\pmod p\)。
因此,对于 \(r\in \mathbb N^*\),有 \((\Delta^{p^r}S)_x=S_{(x+p^r)\bmod n}-S_x\)。当我们需要进行判断时,我们要求 \(S_{(x+p^r)\bmod n}\equiv S_x\pmod p\)。由于 \(x\) 取值的任意性,这个条件等价于 \(S_{(x+\gcd(p^r,n))\bmod n}\equiv S_x\pmod p\)。
注意到,尽管 \(p^r\) 可以很大,但是 \(\gcd(p^r,n)\le n\),是有上界的。不妨设 \(r_0\) 满足 \(p^{r_0}|n,p^{r_0+1}\nmid n\),则当 \(r\ge r_0\) 的时候,\(q_{p^{r}}\) 都等价于 \(\forall 0\le x<n,S_{(x+p^{r_0})\bmod n}\equiv S_x\pmod p\)。
为了解决第一个问题,可行的方法是取一个“充分大”的 \(m\),并检查 \(q_m\) 是否成立。现在我们知道,当 \(r\rightarrow +\infty\) 时,\(p^r\rightarrow +\infty\),而 \(q_{p^r}\) 始终可以被很简单地判断,所以我们已经可以解决第一个问题了。
第二个问题相对来说要简单一点,只需要注意到 \(\Delta\) 是存在结合律的即可。这意味着 \(\Delta^m\) 可以等价地拆成若干个 \(\Delta^{p^r}\) 的“乘积”。
于是,我们马上就有了一个 \(O(np\log n\log p)\) 的二分做法。但实际上倍增即可去掉一个 \(\log p\) 的因子。
更进一步!在倍增过程中,如果 \(\Delta^{p^r} S\) 全是 \(0\),我们可以导出 \(\forall 0\le x<n,S_{(x+p^r)\bmod n}\equiv S_x\pmod p\)。这意味着 \(S\) 可以被收缩到 \(p^r\) 的大小。 于是,在倍增过程中,我们需要考虑的 \(S\) 的大小是逐渐变小的。复杂度即为 \(T(n)=T(\frac n p)+O(pn)=O(np)\)。
代码
#include <cstdio>
#define rep( i, a, b ) for( int i = (a) ; i <= (b) ; i ++ )
#define per( i, a, b ) for( int i = (a) ; i >= (b) ; i -- )
const int MAXN = 3e5 + 5, MAXLOG = 25;
template<typename _T>
inline void Read( _T &x ) {
x = 0; char s = getchar(); bool f = false;
while( ! ( '0' <= s && s <= '9' ) ) { f = s == '-', s = getchar(); }
while( '0' <= s && s <= '9' ) { x = ( x << 3 ) + ( x << 1 ) + ( s - '0' ), s = getchar(); }
if( f ) x = -x;
}
template<typename _T>
inline void Write( _T x ) {
if( x < 0 ) putchar( '-' ), x = -x;
if( 9 < x ) Write( x / 10 );
putchar( x % 10 + '0' );
}
int pw[MAXLOG];
int A[MAXN], B[MAXN];
int N, mod;
inline bool AllZero() {
rep( i, 0, N - 1 ) if( A[i] ) return false;
return true;
}
int main() {
// freopen( "name.in", "r", stdin );
// freopen( "name.out", "w", stdout );
Read( N ), Read( mod );
rep( i, 0, N - 1 ) Read( A[i] ), A[i] %= mod;
int k = 0; for( int x = N ; ! ( x % mod ) ; x /= mod, k ++ );
pw[0] = 1; rep( i, 1, k ) pw[i] = pw[i - 1] * mod;
rep( i, 0, N - 1 )
if( A[i] != A[( i + pw[k] ) % N] )
return puts( "-1" ), 0;
if( AllZero() ) return puts( "0" ), 0;
int ans = 0;
for( int i = k - 1 ; ~ i ; i -- ) {
int n = pw[i + 1], m = pw[i];
while( true ) {
bool flg = true;
rep( i, 0, n - 1 ) {
B[i] = ( A[( i + m ) % n] - A[i] + mod ) % mod;
flg &= B[i] == 0;
}
if( flg ) break;
rep( i, 0, n - 1 ) A[i] = B[i];
ans += m;
}
}
Write( ans + 1 ), putchar( '\n' );
return 0;
}
标签:mathbb,le,题目,pw,int,THUPC2019,Delta,忘记,mod
From: https://www.cnblogs.com/crashed/p/17060455.html