Codeforces 1832 E Combinatorics Problem 解析【难度 2200】

题目地址

https://codeforces.com/problemset/problem/1832/E

题目抽象

给 n, a 1 a_1 a1,x,y,m,k 六个整数,需要进行如下4步操作

  1. 根据 a i = ( a i − 1 ⋅ x + y ) % m , i ∈ [ 2 , n ] a_i=(a_{i-1}\cdot x + y) \% m, i\in[2,n] ai=(ai1x+y)%m,i[2,n] 生成数组a
  2. 根据 b i = ( ∑ j = 1 i ( C i − j + 1 k ⋅ a j ) ) % 998244353 b_i = (\sum_{j=1}^i(C_{i-j+1}^k\cdot a_j)) \% 998244353 bi=(j=1i(Cij+1kaj))%998244353 生成数组b
  3. 根据 c i = b i ⋅ i c_i = b_i\cdot i ci=bii 生成数组c
  4. 计算 c 1 ⊕ c 2 ⊕ ⋯ ⊕ c n c_1 \oplus c_2 \oplus \cdots \oplus c_n c1c2cn 的结果( ⊕ \oplus 代表位运算的异或操作)

数据量:
1 ≤ n ≤ 1 0 7 1\le n\le 10^7 1n107
0 ≤ a 1 , x , y , ≤ m 0\le a_1,x,y,\le m 0a1,x,y,m
2 ≤ m ≤ 998244353 2\le m \le 998244353 2m998244353
1 ≤ k ≤ 5 1\le k \le 5 1k5

题目类型

数学推导

解题思路

第1,3,4步都是非常直观,一直模拟直接计算出来
主要难点就是第二步,根据a计算b
下面进行拆解分析:
粗暴地计算每个 b i b_i bi 的复杂度非常高,由于n最大可能是 1 0 7 10^7 107,需要找一个方式可以让 b i b_i bi 的计算可以在 O ( 1 ) O(1) O(1) 的时间内完成

tips:
一般这种情况都是寻找 b i b_i bi b i − 1 b_{i-1} bi1的关系,使得 b i b_i bi 可以通过 b i − 1 b_{i-1} bi1 快速得出
而找他们的关系,就是将他们展开,然后相减,大部分情况都适用

我们将其展开,然后相减来得出其关系
b i = C i k ⋅ a 1 + C i − 1 k ⋅ a 2 … C 2 k ⋅ a i − 1 + C 1 k ⋅ a i b i − 1 = C i − 1 k ⋅ a 1 + C i − 2 k ⋅ a 2 … C 1 k ⋅ a i − 1 b i − b i − 1 = ( C i k − C i − 1 k ) ⋅ a 1 + ( C i − 1 k − C i − 2 k ) ⋅ a 2 … ( C 2 k − C 1 k ) ⋅ a i − 1 + C 1 k ⋅ a i \begin{array}{clcr} b_i&=&C_i^k\cdot a_1 &+ &C_{i-1}^k\cdot a_2 &\dots &C_2^k\cdot a_{i-1} &+ &C_1^k\cdot a_i \\ b_{i-1}&=&C_{i-1}^k\cdot a_1 &+ &C_{i-2}^k\cdot a_2 &\dots &C_1^k\cdot a_{i-1} \\ b_i-b_{i-1} &=&(C_i^k-C_{i-1}^k)\cdot a_1&+&(C_{i-1}^k-C_{i-2}^k)\cdot a_2&\dots &(C_2^k-C_1^k)\cdot a_{i-1} &+ &C_1^k\cdot a_i \\ \end{array} bibi1bibi1===Cika1Ci1ka1(CikCi1k)a1+++Ci1ka2Ci2ka2(Ci1kCi2k)a2C2kai1C1kai1(C2kC1k)ai1++C1kaiC1kai
∵ \because 组合数有这个性质 C i k = C i k − 1 + C i − 1 k − 1 C_i^k=C_i^{k-1}+C_{i-1}^{k-1} Cik=Cik1+Ci1k1
∴ b i − b i − 1 = ( C i − 1 k − 1 ⋅ a i + … C 1 k − 1 ⋅ a i − 1 ) + C 1 k ⋅ a i \therefore b_i-b_{i-1} = (C_{i-1}^{k-1}\cdot a_i + \dots C_1^{k-1}\cdot a_{i-1}) + C_1^k\cdot a_i bibi1=(Ci1k1ai+C1k1ai1)+C1kai
括号里边的内容是不是很眼熟,和 b i − 1 b_{i-1} bi1非常的像,就是当k为k-1时候的 b i − 1 b_{i-1} bi1
我们将b扩展一维,原本的 b i b_i bi b k , i b_{k,i} bk,i代替,那么就得到
b k , i − b k , i − 1 = b k − 1 , i − 1 + C 1 k ⋅ a i b_{k,i}-b_{k,i-1} = b_{k-1,i-1} + C_1^k\cdot a_i bk,ibk,i1=bk1,i1+C1kai
∴ b k , i = b k , i − 1 + b k − 1 , i − 1 + C 1 k ⋅ a i \therefore b_{k,i} =b_{k,i-1}+ b_{k-1,i-1} + C_1^k\cdot a_i bk,i=bk,i1+bk1,i1+C1kai
所以,我们值需要计算出 b 0 , i b_{0,i} b0,i b k , 0 b_{k,0} bk,0,剩余的 b k , i b_{k,i} bk,i就能通过前序已经计算出的结果得到
根据定义可得
b 0 , i = a i + a i − 1 + … a 1 = b k , i − 1 + a i b_{0,i}=a_i+a_{i-1}+\dots a_1=b_{k,i-1}+a_i b0,i=ai+ai1+a1=bk,i1+ai
b k , 0 = 0 b_{k,0}=0 bk,0=0
再根据 b k , i = b k , i − 1 + b k − 1 , i − 1 + C 1 k ⋅ a i b_{k,i} =b_{k,i-1}+ b_{k-1,i-1} + C_1^k\cdot a_i bk,i=bk,i1+bk1,i1+C1kai (当k=1时, C 1 k = 1 C_1^k=1 C1k=1,其他情况等于0) 就可以根据前置计算所得 O ( 1 ) O(1) O(1)的复杂度计算得出
整体复杂度 O ( n ⋅ k ) O(n\cdot k) O(nk)

代码

#include <bits/stdc++.h>
using namespace std;

const int mod = 998244353;

long long a[10000001];
long long b[6][10000001];

int main() {
  int n, x, y, m, K;
  cin >> n;
  cin >> a[1] >> x >> y >> m >> K;
  for (int i = 2; i <= n; i ++) {
    a[i] = (a[i - 1] * x + y) % m;
  }
  for (int i = 1; i <= n; i ++) {
    b[0][i] = b[0][i-1] + a[i];
  }
  for (int k = 1; k <= K; k ++) {
    for (int i = 1; i <= n; i ++) {
      b[k][i] = (b[k][i - 1] + b[k - 1][i - 1] + (k == 1 ? a[i] : 0)) % mod;
    }
  }
  long long ans = 0;
  for (int i = 1; i <= n; i ++) {
    ans ^= b[K][i] * i;
  }
  cout << ans << endl;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值