xj膜你赛23

1 乘

时间限制: 2s
空间限制: 256MB

1.1 题目描述

你有一个正整数 (a) , 有 (q) 次询问, 每次给定一个正整数 (b_i)
, 求 (a^{b_i}) 的值.
由于答案可能很大, 你只需要输出答案对 (p) 取模的结果。
又由于询问可能很多, 给定一个参数 (k), 你只需要输出对于所有 (k) 的整数倍 (i(0 < i ≤ q)) , 第一
次询问到第 (i) 次询问的结果的异或和.
为了防止输入文件过大, 每次询问的值以以下方法生成:
(b_i) 为第 (i) 次询问的值, 给定 (b_0, l, m, c,i > 0) 时,(b_i) 满足 (b_i = (m ∗ b_i−1 + c)mod l)

1.2 输入格式

第一行四个正整数 (a, p, q, k).
第二行四个正整数 (b_0, l, m, c).

1.3 输出格式

输出 (⌊frac{q}{k}⌋) 行, 第 i 行表示第一次到第 (i ∗ k) 次询问结果的异或和. 你不需要对异或和进行取模.

1.4 样例数据

1.4.1 样例 1 输入

4 3 9 6
5 8 7 7

1.4.2 样例 1 输出

0

1.4.3 样例 1 解释

b1 − b6 分别为 2, 5, 2, 5, 2, 5, 答案都是 1, 异或和为 0.

1.5 数据范围

对于前 10% 的数据, (q = 0);
对于前 50% 的数据, (q ≤ 10^5);
对于另外 20% 的数据, (p = 999983);
对于 100% 的数据, (a ≤ 10^9, q ≤ 10^7, p ≤ 10^9, ⌊frac{q}{k}⌋ ≤ 1000, b_0, l ≤ 10^{12}, m, c ≤ 10^6).

分析

定义两个数组s,t,s储存 (a^1,a^2,...,a^{1000000}) ,t储存 (a^{1000000},a^{2000000},...,a^{10^{12}}),每次的答案即为 (s[b_i\%1000000]*t[i/1000000]\%p)

Code

#include<cstdio>
#define maxn 1000001
using namespace std;
typedef long long D;
D mod,A[maxn+1],B[maxn+1];
D mul(D a,D b){return (a*=b)>=mod?a%mod:a;}
int main(){
    D a,q,k,l,m,c,b,last,Xor=0;
    scanf("%lld%lld%lld%lld%lld%lld%lld%lld",&a,&mod,&q,&k,&last,&l,&m,&c);
    A[0]=1;
    for(D i=1;i<=maxn;i++)A[i]=mul(A[i-1],a);
    B[0]=1;
    for(D i=1;i<=maxn;i++)B[i]=mul(B[i-1],A[maxn]);
    for(D i=1;i<=q;i++){
        b=(m*last+c)%l;
        Xor^=mul(A[b%maxn],B[b/maxn]);
        if(i%k==0)printf("%lld
",Xor);
        last=b;
    }
    return 0;
}

2 树

时间限制: 1s
空间限制: 256MB

2.1 题目描述

你有一个长度为 (n) 的序列, 第 (i) 个数是 (a_i) , 下标从 (1) 开始. 有 (q) 次操作, 可能为:
1 l r k, 表示 (∀x ∈ [l, r]) , 使 (a_x) 变为 (a_x) & (k). 其中 & 表示按位与运算.
2 l r, 表示询问连续子序列 ([l, r]) 中所有元素的和.
3 l r, 表示询问: 如果在 ([l, r]) 之间均匀随机生成两个整数 (x, y,(a_x + a_y)^2) 的期望值. 你只需要输出答案与 ((r − l + 1)^2) 的乘积对 (998244353) 取模的值. 可以证明答案一定是整数.

2.2 输入格式

第一行一个整数 (n) 表示序列长度, 接下来一行 (n) 个整数描述这个序列.
第三行一个整数 (q) 表示操作次数, 接下来 (q) 行每行一次操作, 格式同题目描述.

2.3 输出格式

输出等同于操作 2, 3 次数之和的行数, 每行一个非负整数表示对应询问的答案. 注意操作 2 的答案不需要进行取模.

2.4 样例数据

2.4.1 样例 1 输入

5
8 4 3 5 6
5
2 3 5
3 1 2
1 2 4 3
2 3 5
3 1 2

2.4.2 样例 1 输出

14
608
10
384

2.4.3 样例 1 解释

第三次操作后, 序列变为 ([8, 0, 3, 1, 6]) .

2.5 数据范围

对于前 30% 的数据, (n, q ≤ 100);
对于另 20% 的数据, 没有操作 1;
对于另 20% 的数据, 没有操作 3;
对于 100% 的数据, (n, q ≤ 10^5, ai ≤ 10^9, k ≤ 2^30, 1 ≤ l ≤ r ≤ n) .

分析

2操作为线段树基本操作,3操作其实就是求 $$sum_{iin [x,y]}sum_{jin [x,y]}(a_i+a_j)^2$$ 它等于 $$2* ((y-x+1)* ([x,y]的平方和)+([x,y]的和)^2)$$
在每个节点维护一个和( (sum_i a_i) )与一个平方和( (sum_ia_i^2) )即可。
对于1操作,暴力 (O(n)) 修改(不用懒标记),不过要加一些剪枝:在每个节点维护一个或和,如果 要按位与的数 (k) 按位或上 这个或和 等于 (k) ,那么就没有必要修改此区间了。因为修改和不修改效果一样。
然后就 (AC)

Code

#include<cstdio>
#define maxn 100002
#define mod 998244353ll
#define ch1(p) (p<<1)
#define ch2(p) (p<<1|1)
using namespace std;
typedef long long D;
inline D Plus(D a,D b){return (a+b)%mod;}
inline D mul(D a,D b){return a*b%mod;}
D read(){
    char c=getchar();
    while(c<'0'||c>'9')c=getchar();
    D x=0;
    while(c>='0'&&c<='9'){
        x=(x<<3)+(x<<1)+c-'0';
        c=getchar();
    }
    return x;
}
void write(const D x){
    if(x>=10)write(x/10);
    putchar(x%10+'0');
}
D a[maxn],n;
struct node{
    D sum,sqrsum,Or;
    node():sum(0),sqrsum(0),Or(0){}
};
node t[maxn<<2];
void pushup(D p){
    t[p].sum=t[ch1(p)].sum+t[ch2(p)].sum;
    t[p].sqrsum=Plus(t[ch1(p)].sqrsum,t[ch2(p)].sqrsum);
    t[p].Or=t[ch1(p)].Or|t[ch2(p)].Or;
}
void build(D p,D l,D r){
    if(l==r){
        t[p].sum=a[l];
        t[p].sqrsum=mul(a[l]%mod,a[l]%mod);
        t[p].Or=a[l];
        return;
    }
    D mid=(l+r)>>1;
    build(ch1(p),l,mid);
    build(ch2(p),mid+1,r);
    pushup(p);
}
void change(D p,D l,D r,D seg_l,D seg_r,D k){
    if(l==r){
        t[p].sum&=k;
        t[p].sqrsum=mul(t[p].sum%mod,t[p].sum%mod);
        t[p].Or=t[p].sum;
    }
    if(seg_l<=l&&r<=seg_r&&(t[p].Or|k)==k)return;
    D mid=(l+r)>>1;
    if(seg_l<=mid)change(ch1(p),l,mid,seg_l,seg_r,k);
    if(seg_r>mid)change(ch2(p),mid+1,r,seg_l,seg_r,k);
    pushup(p);
}
const D query1(D p,D l,D r,D seg_l,D seg_r){
    if(seg_l<=l&&r<=seg_r){
        return t[p].sum;
    }
    D mid=(l+r)>>1;
    D ret=0;
    if(seg_l<=mid)ret+=query1(ch1(p),l,mid,seg_l,seg_r);
    if(seg_r>mid)ret+=query1(ch2(p),mid+1,r,seg_l,seg_r);
    return ret;
}
const node query2(D p,D l,D r,D seg_l,D seg_r){
    if(seg_l<=l&&r<=seg_r){
        return t[p];
    }
    D mid=(l+r)>>1;
    node ret;
    if(seg_l<=mid&&seg_r>mid){
        node tmp1=query2(ch1(p),l,mid,seg_l,seg_r),tmp2=query2(ch2(p),mid+1,r,seg_l,seg_r);
        ret.sum=Plus(tmp1.sum%mod,tmp2.sum%mod);
        ret.sqrsum=Plus(tmp1.sqrsum,tmp2.sqrsum);
    }
    else{
        if(seg_l<=mid)ret=query2(ch1(p),l,mid,seg_l,seg_r);
        if(seg_r>mid)ret=query2(ch2(p),mid+1,r,seg_l,seg_r);
        ret.sum%=mod;
    }
    return ret;
}
 
signed main(){
    n=read();
    for(D i=1;i<=n;i++)a[i]=read();
    build(1,1,n);
    D q=read(),mo,x,y,k;
    while(q--){
        mo=read(),x=read(),y=read();
        if(mo==1){
            k=read();
            change(1,1,n,x,y,k);
        }
        else if(mo==2){
            write(query1(1,1,n,x,y));
            putchar('
');
        }
        else{
            node tmp=query2(1,1,n,x,y);
            write(mul(2,Plus(mul(y-x+1,tmp.sqrsum),mul(tmp.sum%mod,tmp.sum%mod))));
            putchar('
');
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/BlogOfchc1234567890/p/9896955.html