[前缀积][后缀积][分块] Jzoj 100035 区间

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

 

题解

  • 首先,将s数列构造出来
  • 然后分块,每k个一块
  • 可以预处理出块中前缀积和后缀积
  • 如果当前刚好是一个块的话,直接将块中积异或ans
  • 如果不是,就是区间分成上一个后缀积乘前缀积

代码

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <cmath>
 4 using namespace std;
 5 int n,k,mo,b,c,d,ans,s[20000010],k1[20000010],k2[20000010];
 6 int main()
 7 {
 8     freopen("range.in","r",stdin);
 9     freopen("range.out","w",stdout);
10     scanf("%d%d%d",&n,&k,&mo);
11     scanf("%d%d%d%d",&s[1],&b,&c,&d);
12     for (int i=2;i<=n;i++) s[i]=(s[i-1]*1LL*b+c)%d;
13     int cnt=n/k;
14     for (int i=0;i<cnt;i++)
15     {
16         int w=i*k+1;
17         k1[w]=s[w];
18         for (int j=w+1;j<w+k;j++) k1[j]=k1[j-1]*1LL*s[j]%mo;
19         k2[w+k-1]=s[w+k-1];
20         for (int j=w+k-2;j>=w;j--) k2[j]=k2[j+1]*1LL*s[j]%mo;
21     }
22     if (n%k!=0)
23     {
24         int w=cnt*k+1;
25         k1[w]=s[w];
26         for(int i=w+1;i<=n;i++) k1[i]=k1[i-1]*1LL*s[i]%mo;
27         k2[n]=s[n];
28         for(int i=n-1;i>=w;i--) k2[i]=k2[i+1]*1LL*s[i]%mo;
29     }
30     for (int i=1;i<=n-k+1;i++)
31         if (i%k==1)    ans=ans^k1[i+k-1];
32         else ans=ans^k2[i]*1LL*k1[i+k-1]%mo;
33     printf("%d",ans);
34     return 0;
35 }

 

posted @ 2018-08-09 19:56  BEYang_Z  阅读(357)  评论(0编辑  收藏  举报