首页 > 其他分享 >「THUPC2019」令人难以忘记的题目名称

「THUPC2019」令人难以忘记的题目名称

时间:2023-01-18 19:45:31浏览次数:62  
标签:mathbb le 题目 pw int THUPC2019 Delta 忘记 mod

题目

点这里看题目。


现在有一个长度为 \(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 可以保证必胜”。则两个问题分别是:

  1. 是否 \(\exist m\in \mathbb N,\text{s.t. } q_m\)​。
  2. 求出 \(\min\{m\in \mathbb N|q_m\land (\neg q_{m-1}\lor m=0)\}\)​​。

我们不妨先研究一下 \(q_m\)​ 的等价命题。考虑一些比较小的情况:

  1. \(m=0\)​​ 时,这就意味着 \(S\)​ 全为 \(0\)​​。

  2. \(m=1\)​​ 时,可以发现 \(S\)​​ 包含的元素全部相同为一种可能的情况。利用反证法容易证明 \(q_1\Leftrightarrow\)​​ “\(S\)​​ 中的数全部相同”。

  3. \(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\)。​

    根据推理过程,这是一个必要条件,其充分性也容易证明。

  4. 归纳一下已有的结果,我们发现 $q_m(m=0,1,2)\Leftrightarrow $​​​​​“在模 \(p\)​​​ 意义下,\(\Delta^m S\)​​​​​ 中的数全为 \(0\)​​​​​“。

    推广到 \(m\in \mathbb N\),这个关系都是成立的。证明可以使用数学归纳法,限于篇幅此处略去。

现在,我们要做的就是:

  1. 判定是否 \(\exist m\in \mathbb N\)​​​,使得在模 \(p\)​​​ 意义下,\(\Delta^mS\)​​​ 中的数全为 \(0\)​​​。
  2. 求一个最小的 \(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

相关文章

  • C/C++数据结构题目[2023-01-16]
    C/C++数据结构题目[2023-01-16]以下内容二选一题目1:校园导航系统的设计与实现问题描述:校园导航系统能够提供校园内场所信息和路径查询。以传媒大学校园为例,校园内包......
  • JumpServer 登录密码忘记及用户锁定如何处理
    概述本文主要介绍堡垒机使用过程中产生的密码相关问题。主要包括忘记密码、密码过期、以及登录频繁账号被锁定。忘记密码,密码过期问题描述在使用JumpServer的过程中,可能会......
  • 题目选讲
    题目选讲\(\text{ByDaiRuiChen007}\)I.[洛谷4637]-扫雷机器人ProblemLink思路分析考虑求出期望的过程:每种引爆地雷的顺序,共有\(n!\)种情况对于每种顺序,计......
  • 130116 学英语新的感悟-单词与句子的忘记
    周末,重拾欧陆的句子的记忆,有了新的感悟.你的学习的基本架构是单词--->短语--->句子.而你学习的根本目的,就是能够听懂,会写,会说,核心就是你如何了这个单词,知道如何去......
  • 案例题目(概括异常,如:WPF 及winfrom界面假死)
    5.1   案例题目(概括异常,如:WPF及winfrom界面假死) 5.1.1           异常描述占用主UI线程,运行耗时程序代码导致界面假死无法点击及操作。  5.1.2......
  • 253. 会议室 II(会员题目)
    题目给你输入若干形如[begin,end]的区间,代表若干会议的开始时间和结束时间,请你计算至少需要申请多少间会议室。函数签名如下://返回需要申请的会议室数量intminMeeting......
  • ROIS冬令营 MISC题目
    T1:TwoDimensional鼠鼠怕别人发现他的秘密,作为一只有独特能力的三维生物,他把这个秘密破坏,降维了,你能找到这个秘密吗?下面是某人偷出的加密文件这个点开txt文件以后是个b......
  • 忘记gitlab的root的密码如何修复(Linux环境)
    一进入到gitlab服务器,输入gitlab-railsconsoleproduction命令进入到gitlab控制台gitlab-railsconsoleproduction二输入如下指令获取root用户变量user=User.......
  • 题目:该代码将会输出什么
    A.10B.9C.8D.7#include<stdio.h>intmain(){inta,b;for(a=1,b=1;a<=200;a++){if(b>=20)break;if(b%3==1){b+=3;continue;}b=......
  • LeetCode刷题(59)~使数组中所有元素相等的最小操作数【第202场周赛:题目二】
    题目描述存在一个长度为n的数组arr,其中arr[i]=(2*i)+1(0<=i<n)。一次操作中,你可以选出两个下标,记作x和y(0<=x,y<n)并使arr[x]减去1、arr[y]......