# 环鸽的数列（数列的通项，区间加等比数列，区间求和）

### 题意：

$op=1$：区间 $[l,\ r]$ 每个位置加上 $F_{i-l+1}$

$op=2$：输出区间 $[l,\ r]$ 的和膜 $998244353$ 的值

### 若 $s=r$

$F_n-rF_{n-1}=r(F_{n-1}-rF_{n-2})$，继续化简得到 $F_n=rF_{n-1}+r^{n-2}(F_{2}-rF_{1})$

$F_n=r^{n-3}*(2rF_2-r^2F_1)+(n-3)r^{n-2}*(F_2-rF_1)$

### 若 $s\neq r$

$F_n-rF_{n-1}=s(F_{n-1}-rF_{n-2})$，继续化简得到 $F_n-rF_{n-1}=s^{n-2}(F_{2}-rF_{1})$

$F_n-sF_{n-1}=r(F_{n-1}-sF_{n-2})$，继续化简得到 $F_n-sF_{n-1}=r^{n-2}(F_{2}-sF_{1})$

### Code：

// F_n = \frac{1}{\sqrt{17}}*((\frac{3+\sqrt{17}}{2})^n-(\frac{3-\sqrt{17}}{2})^n)
// F_n = inv_sqrt17*(x_0^n-x_1^n)
#include <bits/stdc++.h>
#define ll long long
#define sc scanf
#define pr printf
#define lson left,mid,k<<1,op
#define rson mid+1,right,k<<1|1,op
#define imid int mid=(left+right)>>1;
using namespace std;
const int MAXN = 1e5 + 5;
const ll mod = 998244353;
const ll sqrt17 = 473844410;
const ll inv_sqrt17 = 438914993;
const ll x[2] = { 736044383,262199973 };
struct node
{
int l;
int r;
ll mark;
ll sum;
}que[MAXN * 4][2];
ll a[MAXN];
ll facq[MAXN][2];                          //power(x[op],i)
const ll inv[2] = { 932694360,315111081 }; //power(x[op]-1,mod-2)
void init()
{
facq[0][0] = 1;
facq[0][1] = 1;
for (int i = 1; i < MAXN; i++)
{
facq[i][0] = facq[i - 1][0] * x[0] % mod;
facq[i][1] = facq[i - 1][1] * x[1] % mod;
}
}
ll power(ll a, ll b)
{
ll res = 1;
while (b)
{
if (b & 1)
res = res * a % mod;
a = a * a % mod;
b >>= 1;
}
return res;
}
ll calcnth(ll a1, ll n, int op)
{
ll an = a1 * facq[n - 1][op] % mod;
return an;
}
ll calcsum(ll a1, ll n, ll op)
{
ll q = x[op];
ll an = a1 * facq[n - 1][op] % mod;
ll ans = (an * q % mod - a1 + mod) * inv[op] % mod;
return ans;
}
void up(int k, int op)
{
que[k][op].sum = (que[k << 1][op].sum + que[k << 1 | 1][op].sum) % mod;
}
void down(int k, int op)
{
if (que[k][op].mark)
{
que[k << 1][op].mark = (que[k << 1][op].mark + que[k][op].mark) % mod;
que[k << 1][op].sum = (que[k << 1][op].sum + calcsum(que[k][op].mark, (que[k << 1][op].r - que[k << 1][op].l + 1), op)) % mod;
ll rst = calcnth(que[k][op].mark, que[k << 1][op].r - que[k << 1][op].l + 1 + 1, op);
que[k << 1 | 1][op].mark = (que[k << 1 | 1][op].mark + rst) % mod;
que[k << 1 | 1][op].sum = (que[k << 1 | 1][op].sum + calcsum(rst, (que[k << 1 | 1][op].r - que[k << 1 | 1][op].l + 1), op)) % mod;
que[k][op].mark = 0;
}
}
void build(int left, int right, int k, int op)
{
que[k][op].l = left;
que[k][op].r = right;
que[k][op].mark = 0;
que[k][op].sum = 0;
if (left == right)
{
que[k][op].sum = 0;
return;
}
imid;
build(lson);
build(rson);
up(k, op);
}
void update(int left, int right, int k, int op, int ql, int qr, ll val)
{
if (qr < left || right < ql)
return;
if (ql <= left && right <= qr)
{
ll st = calcnth(val, left - ql + 1, op);
que[k][op].mark = (que[k][op].mark + st) % mod;
que[k][op].sum = (que[k][op].sum + calcsum(st, que[k][op].r - que[k][op].l + 1, op)) % mod;
return;
}
down(k, op);
imid;
update(lson, ql, qr, val);
update(rson, ql, qr, val);
up(k, op);
}
ll query(int left, int right, int k, int op, int ql, int qr)
{
if (qr < left || right < ql)
return 0;
if (ql <= left && right <= qr)
return que[k][op].sum;
down(k, op);
imid;
return (query(lson, ql, qr) + query(rson, ql, qr)) % mod;
}
int main()
{
init();
int n, m;
sc("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
{
sc("%lld", &a[i]);
a[i] = (a[i] + a[i - 1]) % mod;
}
build(1, n, 1, 0);
build(1, n, 1, 1);
while (m--)
{
int op, ql, qr;
sc("%d%d%d", &op, &ql, &qr);
if (op == 1)
{
update(1, n, 1, 0, ql, qr, x[0]);
update(1, n, 1, 1, ql, qr, x[1]);
}
else
{
ll ans1 = query(1, n, 1, 0, ql, qr);
ll ans2 = query(1, n, 1, 1, ql, qr);
ll ans = inv_sqrt17 * (ans1 - ans2 + mod) % mod;
ans = (ans + a[qr] - a[ql - 1] + mod) % mod;
pr("%lld\n", ans);
}
}
}
/*
4 2
0 0 0 0
1 1 1
2 1 1
*/

10-27 84

05-28 1325

08-16 175

03-03 4592

07-18 689

04-09 21

02-17 523

05-17 149

09-24 69

06-05 404

03-19 83万+

04-14 62万+

03-13 16万+

03-01 14万+

03-08 5万+

03-08 8万+

03-09 3049

03-10 14万+

03-10 20万+

03-12 12万+

#### 如果你是老板，你会不会踢了这样的员工？

©️2019 CSDN 皮肤主题: 技术工厂 设计师: CSDN官方博客