Description
Input
Output
Sample Input
sample1: 4 2 10 5 1 1 10 sample2: 1000 97 96998351 41 1668 505 2333
Sample Output
sample1: 4 sample2: 1749769
Data Constraint
题解:
参考某dalao的代码
我们将这个长为n的序列分为几段长度为k的序列,若不能整分就单独处理多出来的一截
对于一个长度为k的小段,我们处理前缀积和后缀积,需要注意下标+1-1之类的
处理出来有什么好处呢?我们O(2n)初始化后,后面求Tj就几乎是O(1)的了
实现方式是1到n-k+1跑一遍,若i % k等于1,就说明这一段T正好是一段我们刚才分出来的一段
这里就只需要一个前缀积或者后缀积
其他情况,就像Tj被一刀两断,前一段我们用一个后缀积,后一段我们用一个前缀积
然后就是直接用longlong数组要MLE,这个dalao用了一个神奇的乘1LL,貌似是强转longlong就过了= =
果然还是您太强啦,我太弱啦
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<climits>
#include<iomanip>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#define MAXA 20000005
#define ipt(x) scanf("%d",&x)
using namespace std;
typedef long long LL;
int n,k,MOD,Ans,Blocknum,head,Pre[MAXA],Back[MAXA];
int A,B,C,D,S[MAXA];
int main() {
// freopen("range.in","r",stdin);
// freopen("range.out","w",stdout);
scanf("%d %d %d",&n,&k,&MOD);
scanf("%d %d %d %d",&A,&B,&C,&D);
S[1] = A;
for(int i=2;i<=n;i++)
S[i] = (S[i-1] * 1LL * B + C) % D;
Blocknum = n / k;
for(int j=0;j<Blocknum;j++) {
head = j * k + 1;
Pre[head] = S[head];
for(int i=head+1;i<head+k;i++)
Pre[i] = Pre[i-1] * 1LL * S[i] % MOD;
Back[head+k-1] = S[head+k-1];
for(int i=head+k-2;i>=head;i--)
Back[i] = Back[i+1] * 1LL * S[i] % MOD;
}
if(n % k) {
head = Blocknum * k + 1;
Pre[head] = S[head];
for(int i=head+1;i<=n;i++)
Pre[i] = Pre[i-1] * 1LL * S[i] % MOD;
Back[n] = S[n];
for(int i=n-1;i>=head;i--)
Back[i] = Back[i+1] * 1LL * S[i] % MOD;
}
for(int i=1;i<=n-k+1;i++) {
if(i % k == 1)
Ans ^= Pre[i+k-1];
else Ans ^= Back[i] * 1LL * Pre[i+k-1] % MOD;
}
printf("%d",Ans);
}