[ZROI2021]序列变换

280 篇文章 1 订阅

题目

题目描述
定义一个从序列到序列的映射 f ( a ) = b f(a)=b f(a)=b 满足
b i = ⨁ j = 0 k − 1 a ( i + j )   m o d   n b_i=\bigoplus_{j=0}^{k-1}a_{(i+j)\bmod n} bi=j=0k1a(i+j)modn

其中 a , b a,b a,b 都是下标在 0 0 0 n − 1 n{-}1 n1 之间的非负整数序列。

现在你需要求出 f T ( a ) = f T − 1 [ f ( a ) ]    ( T > 1 ) f^T(a)=f^{T-1}[f(a)]\;(T>1) fT(a)=fT1[f(a)](T>1),规定 f 1 ( a ) = f ( a ) f^1(a)=f(a) f1(a)=f(a) 。即对 a a a 进行 T T T f f f 变换后的结果。

数据范围与提示
n ⩽ 5 × 1 0 5 ,    T ⩽ 1 0 18 n\leqslant 5\times 10^5,\;T\leqslant 10^{18} n5×105,T1018

思路

直接快速幂不可以过。但是很特殊的是,我们快速幂只是在求
( 1 + x + x 2 + ⋯ + x k − 1 ) T   m o d   2 \left(1+x+x^2+\cdots+x^{k-1}\right)^T\bmod 2 (1+x+x2++xk1)Tmod2

显然这个式子等于
( 1 − x k 1 − x ) T = [ ∑ i = 0 T ( T i ) ( − 1 ) i x i k ] [ ∑ i = 0 + ∞ ( i + T − 1 T − 1 ) x i ] \left(\frac{1-x^k}{1-x}\right)^T=\left[\sum_{i=0}^{T}{T\choose i}(-1)^ix^{ik}\right]\left[\sum_{i=0}^{+\infty}{i+T-1\choose T-1}x^i\right] (1x1xk)T=[i=0T(iT)(1)ixik][i=0+(T1i+T1)xi]

即分子分母都展开的结果。这个式子感觉不好整,因为组合数太复杂了……

不过,既然是模 2 2 2 意义下,很容易让人想起卢卡斯定理,
( n m )   m o d   2 = [ m ⊆ n ] {n\choose m}\bmod 2=\big[m\subseteq n\big] (mn)mod2=[mn]

这里用集合符号表示了二进制位的情况。即 m m m n n n 的按位与结果是 m m m

不妨设 T = 2 t    ( t ⩾ 1 ) T=2^t\;(t\geqslant 1) T=2t(t1),那么左边那个括号只有两项,右边那个括号只有 2 t ∣ i 2^t\mid i 2ti 的项。于是
≡ ( 1 + x 2 t k ) ( ∑ i = 0 + ∞ x 2 t i ) ≡ 1 + x 2 t + x 2 t × 2 + ⋯ + x 2 t ( k − 1 ) ( m o d 2 ) \equiv(1+x^{2^tk})\left(\sum_{i=0}^{+\infty}x^{2^ti}\right)\\ \equiv 1+x^{2^t}+x^{2^t\times 2}+\cdots+x^{2^t(k-1)}\pmod 2 (1+x2tk)(i=0+x2ti)1+x2t+x2t×2++x2t(k1)(mod2)

这个东西就很有规律了——以 2 t 2^t 2t 为步长,每个点变为前面 k k k 步的值的异或值。作个 2 t 2^t 2t 步长的前缀和,进行一次这种变换就是 O ( n ) \mathcal O(n) O(n) 的了。

问题只是 T T T 不是二的幂;二进制拆分就完了。复杂度 O ( n log ⁡ T ) \mathcal O(n\log T) O(nlogT)

代码

#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
typedef long long int_;
inline int readint(){
	int a = 0; char c = getchar(), f = 1;
	for(; c<'0'||c>'9'; c=getchar())
		if(c == '-') f = -f;
	for(; '0'<=c&&c<='9'; c=getchar())
		a = (a<<3)+(a<<1)+(c^48);
	return a*f;
}
inline void writeint(int x){
	if(x > 9) writeint(x/10);
	putchar((x-x/10*10)^48);
}

const int MaxN = 500005;
int a[MaxN], b[MaxN], n, k;
bool vis[MaxN]; // the index
void change(long long T){
	if((T %= n) == 0){
		if(k&1) return ; // make no difference
		memset(a,0,n<<2); return ;
	}
	memset(vis,0,n); // clear
	for(int x=0; !vis[x]; ++x){
		int p = 0, all = 0;
		for(int i=x; !vis[i]; i=(i+T)%n)
			all ^= a[i], ++ p, vis[i] = 1;
		int now = 0, fr = (x+k*T)%n;
		for(int i=x; i!=fr; i=(i+T)%n)
			now ^= a[i]; // k-th number
		for(int i=fr; true; i=(i+T)%n){
			now ^= a[(i-k*T%n+n)%n];
			b[i] = (now ^= a[i]);
			if((k/p)&1) b[i] ^= all;
			if((i+T)%n == fr) break;
		}
	}
	memcpy(a,b,n<<2); // copy back
}

int main(){
	n = readint(), k = readint();
	long long T; scanf("%lld",&T);
	for(int i=0; i<n; ++i)
		a[n-1-i] = readint();
	while(T) change(T&-T), T ^= (T&-T);
	writeint(a[n-1]);
	for(int i=1; i<n; ++i){
		putchar(' ');
		writeint(a[n-1-i]);
	}
	return 0;
}

后记

更强力的关系是 F ( x ) p   m o d   p = F ( x p )    ( p ∈ P ) F(x)^p\bmod p=F(x^p)\;(p\in{\Bbb P}) F(x)pmodp=F(xp)(pP),其中 P \Bbb P P 是质数集。证明方法也是利用卢卡斯定理:当 F ( x ) F(x) F(x) 是单项式时,显然成立;当 F ( x ) F(x) F(x) 有至少两项时,肯定可以拆成 G ( x ) + H ( x ) G(x)+H(x) G(x)+H(x),于是
[ G ( x ) + H ( x ) ] p = ∑ i = 0 p ( p i ) ⋅ G ( x ) i ⋅ H ( x ) p − i \big[G(x)+H(x)\big]^p=\sum_{i=0}^{p}{p\choose i}\cdot G(x)^i\cdot H(x)^{p-i} [G(x)+H(x)]p=i=0p(ip)G(x)iH(x)pi

只有 i ∈ { 0 , p } i\in\{0,p\} i{0,p} ( p i )   m o d   p ≠ 0 {p\choose i}\bmod p\ne 0 (ip)modp=0,所以其实
F ( x ) p ≡ G ( x ) p + H ( x ) p ( m o d p ) F(x)^p\equiv G(x)^p+H(x)^p\pmod{p} F(x)pG(x)p+H(x)p(modp)

根据归纳法(项数从小到大),我们推出
F ( x ) p ≡ G ( x p ) + H ( x p ) = F ( x p ) ( m o d p ) F(x)^p\equiv G(x^p)+H(x^p)=F(x^p)\pmod{p} F(x)pG(xp)+H(xp)=F(xp)(modp)

如果取 F ( x ) = f ( x ) p ≡ f ( x p ) ( m o d p ) F(x)=f(x)^p\equiv f(x^p)\pmod{p} F(x)=f(x)pf(xp)(modp),你就得到了有趣的结论
[ f ( x ) p ] p ≡ f ( x p ) p ( m o d p ) ⇒ f ( x ) p 2 ≡ f ( x p 2 ) ( m o d p ) [f(x)^p]^p\equiv f(x^p)^p\pmod{p}\\ \Rightarrow f(x)^{p^2}\equiv f(x^{p^2})\pmod{p} [f(x)p]pf(xp)p(modp)f(x)p2f(xp2)(modp)

多迭代几次,你就会得到本题中使用的式子。本题是 p = 2 p=2 p=2 的特殊情况。
f ( x ) p t = f ( x p t ) f(x)^{p^t}=f\left(x^{p^t}\right) f(x)pt=f(xpt)

2022/8/5   update \texttt{2022/8/5 update} 2022/8/5 update:该式子也可以用二项式系数直接计算得到,但现在看来,似乎还没有这种构造方法简洁 😄

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值