列表

详情


NC206048. 环鸽的数列

描述

有一天 给环鸽出了一道题。环鸽看题罢,嘿嘿一笑道:“这题简单,我见过”。一天过去了, 问环鸽有没有把题切了。环鸽:滑稽挠头.gif......

现在环鸽悄悄找到你来寻求帮助。你能不能帮帮环鸽呢?
环鸽给了你一个长为 的数列 a_i,以及一个递推数列 F_i。其中 ; ; 。即它的前几项是: 。给了你下面两种操作:

1. 给你一次操作 "" ,表示对于所有 a_i 加上
2. 给你一次询问 "" ,表示对a_i 求和,答案对 取模。

输入描述

第一行两个整数  

第二行 个整数

后面 行没行三个整数 ,表示一次询问。

输出描述

对于每个询问输出一行整数,表示其答案。

示例1

输入:

4 4
1 2 3 4
1 1 4
2 1 4
1 2 4
2 1 3

输出:

64
25

说明:

初始序列为 \ [1,2,3,4]

第一次操作后为 \ [2,5,14,43] ,第一次询问 \ 2+5+14+43=64

第二次操作后为 \ [2,6,17,54] ,第二次询问 \ 2+6+17=25

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(clang++11) 解法, 执行用时: 304ms, 内存消耗: 10616K, 提交时间: 2021-01-24 22:05:33

#include <bits/stdc++.h>
#define mp make_pair
#define pb push_back
#define sz(x) (int)x.size()
#define all(x) begin(x), end(x)
#define fi first
#define se second
#define debug(x) cerr << #x << " " << x << '\n'
using namespace std;
using ll = long long;
using pii = pair<int,int>;
using pli = pair<ll,int>;
const int INF = 0x3f3f3f3f, N = 1e5 + 5;
const ll LINF = 1e18 + 5;
constexpr int mod = 998244353, a = 438914993, b = 736044383, c = 262199973;
int sum[N];
int n, m, x[N];
inline void mul(int &a, int b) { a = 1ll*a*b%mod; }
inline int Mul(int a, int b) { return 1ll*a*b%mod; }
inline void add(int &a, int b) { a+=b; if(a>=mod) a-=mod; }
inline int Add(int a, int b) { a+=b; if(a>=mod) return a-mod; return a; }
inline void sub(int &a, int b) { a-=b; if(a<0) a+=mod; }
inline int Sub(int a, int b) { a-=b; if(a<0) return a+mod; return a; }
int powmod(int a, int b)
{
	int ans = 1;
	while(b)
	{
		if(b&1) ans = Mul(ans, a);
		a = Mul(a, a);
		b >>= 1;
	}
	return ans;
}
struct SegTree
{
	#define ls (p<<1)
	#define rs (p<<1|1)
	int inv, pw[N]; 
	struct seg
	{
		int l, r, sum, tag;
	}t[N<<2];
	void init(int q)
	{
		pw[0] = 1;
		for(int i=1; i<=n; i++) pw[i] = Mul(pw[i-1], q)%mod;
		inv = powmod(q-1, mod-2);
	}
	void setval(int p, int v)
	{
		add(t[p].sum, Mul(Mul(v, Sub(pw[t[p].r-t[p].l+1], 1)), inv));
		add(t[p].tag, v);
	}
	void pushup(int p)
	{
		t[p].sum = Add(t[ls].sum, t[rs].sum);
	}
	void pushdown(int p)
	{
		setval(ls, t[p].tag); setval(rs, Mul(t[p].tag, pw[t[rs].l-t[ls].l]));
		t[p].tag = 0;
	}
	void build(int p, int l, int r)
	{
		t[p].l = l, t[p].r = r;
		if(l==r) return;
		int mid = (l+r)>>1;
		build(ls, l, mid); build(rs, mid+1, r);
		pushup(p);
	}
	void upd(int p, int x, int y)
	{
		int l = t[p].l, r = t[p].r;
		if(l>=x && r<=y) 
		{
			setval(p, pw[l-x+1]);
			return;
		}
		if(t[p].tag) pushdown(p);
		int mid = (l+r)>>1;
		if(x<=mid) upd(ls, x, y);
		if(y>mid) upd(rs, x, y);
		pushup(p);
	}
	int ask(int p, int x, int y)
	{
		int l = t[p].l, r = t[p].r;
		if(l>=x && r<=y) return t[p].sum;
		if(t[p].tag) pushdown(p);
		int mid = (l+r)>>1, ans = 0;
		if(x<=mid) add(ans, ask(ls, x, y));
		if(y>mid) add(ans, ask(rs, x, y));
		return ans;
	}
	#undef ls
	#undef rs
}T1, T2;
int main()
{
	scanf("%d%d", &n, &m);
	for(int i=1; i<=n; i++) scanf("%d", x+i);
	for(int i=1; i<=n; i++) sum[i] = Add(sum[i-1], x[i]);
	T1.init(b); T2.init(c);
	T1.build(1, 1, n); T2.build(1, 1, n);
	while(m--)
	{
		int op, l, r;
		scanf("%d%d%d", &op, &l, &r);
		if(op==1)
		{
			T1.upd(1, l, r);
			T2.upd(1, l, r);
		}
		else
		{
			int ans = Mul(Sub(T1.ask(1, l, r), T2.ask(1, l, r)), a);
			add(ans, Sub(sum[r], sum[l-1]));
			printf("%d\n", ans);
		}
	}
	return 0;
}

上一题