Description

Transmission Gate

你需要维护一个长度为\(n \leq 300000\) 的数列,兹词两个操作:

1.给一个区间加上一个fibonacci数列,规定\(f[0] = 0, f[1] = 1, f[2] = 1\)

2.查询一段区间的和。对1e9+9取模

操作个数m不超过300000.

Solution

​ 这一题其实要考虑Fibonacci数列的两个性质:

​ (i)\(\sum_{i = 1}^{n} fib(i) = f(n + 2) - 1\)

​ (ii)令\(S_i = S_{i - 1} + S_{i - 2}\), 其中\(S_1 = a, S_2 = b\)

​ 那么\(S_i = aFib(i - 1) + bFib(i - 2)\)

​ 那么就很好做了, 在线段树中, 我们要只要记数列的前两项就可以方便的对数列进行求和,pushdown等操作.

​ 这题细节比较多,相关部分见代码。

Code

#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(int i = (a), i##_end_ = (b); i <= i##_end_; ++i)
#define drep(i, a, b) for(int i = (a), i##_end_ = (b); i >= i##_end_; --i)
#define clar(a, b) memset((a), (b), sizeof(a))
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define Debug(s) debug("The massage in line %d, Function %s: %s\n", __LINE__, __FUNCTION__, s)
typedef long long LL;
typedef long double LD;
const int BUF_SIZE = (int)1e6 + 10;
struct fastIO {
char buf[BUF_SIZE], buf1[BUF_SIZE];
int cur, cur1;
FILE *in, *out;
fastIO() {
cur = BUF_SIZE, in = stdin, out = stdout;
cur1 = 0;
}
inline char getchar() {
if(cur == BUF_SIZE) fread(buf, BUF_SIZE, 1, in), cur = 0;
return *(buf + (cur++));
}
inline void putchar(char ch) {
*(buf1 + (cur1++)) = ch;
if (cur1 == BUF_SIZE) fwrite(buf1, BUF_SIZE, 1, out), cur1 = 0;
}
inline int flush() {
if (cur1 > 0) fwrite(buf1, cur1, 1, out);
return cur1 = 0;
}
}IO;
#define getchar IO.getchar
#define putchar IO.putchar
int read() {
char ch = getchar();
int x = 0, flag = 1;
for(;!isdigit(ch); ch = getchar()) if(ch == '-') flag *= -1;
for(;isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
return x * flag;
}
void write(int x) {
if(x < 0) putchar('-'), x = -x;
if(x >= 10) write(x / 10);
putchar(x % 10 + 48);
}
void putString(char s[], char EndChar = '\n') {
rep(i, 0, strlen(s) - 1) putchar(*(s + i));
if(~EndChar) putchar(EndChar);
} #define Maxn 300009
const LL Mod = 1000000009;
int n, a[Maxn], m; LL f[Maxn];
struct node { LL x, y; };
LL FibDelta(LL F1, LL F2, LL len) {
LL res = 0;
if(len >= 1) (res += F1) %= Mod;
if(len >= 2) (res += F2) %= Mod;
if(len >= 3) (res += (F2 * (f[len + 1] - 2ll) % Mod + F1 * (f[len] - 1ll) % Mod) % Mod) %= Mod;
return res;
}// It needs to analysis in different conditions
node FibForward(node s, int len) {
LL c = s.x * f[len] % Mod + s.y * f[len + 1] % Mod, d = s.x * f[len + 1] % Mod + s.y * f[len + 2] % Mod;
return (node){c % Mod, d % Mod};
}
namespace SGMT_tree {
LL tree[Maxn << 2], beg[Maxn << 2][2], val[Maxn << 2];
#define lc(x) (x) << 1
#define rc(x) (x) << 1 | 1
#define ls rt << 1, l, mid
#define rs rt << 1 | 1, mid + 1, r
void pushup(int rt) { tree[rt] = (1ll * tree[lc(rt)] + 1ll * tree[rc(rt)]) % Mod; }
void pushdown(int rt, int l, int r) {
int mid = (l + r) >> 1;
if(val[rt]) {
LL &a = beg[rt][0], &b = beg[rt][1];
(beg[lc(rt)][0] += a) %= Mod, (beg[lc(rt)][1] += b) %= Mod;
(tree[lc(rt)] += FibDelta(a, b, mid - l + 1)) %= Mod;
val[lc(rt)] = 1; LL c = a * f[mid - l] + b * f[mid - l + 1], d = a * f[mid - l + 1] + b * f[mid - l + 2];
c %= Mod, d %= Mod;
(beg[rc(rt)][0] += c) %= Mod, (beg[rc(rt)][1] += d) %= Mod;
(tree[rc(rt)] += FibDelta(c, d, r - mid)) %= Mod;
val[rc(rt)] = 1;
beg[rt][0] = beg[rt][1] = 0;
val[rt] = 0;
}
}
void build(int rt, int l, int r) {
if(l == r) {
tree[rt] = a[l];
return ;
}
int mid = (l + r) >> 1;
build(ls), build(rs);
pushup(rt);
}
void modify(int rt, int l, int r, int x, int y, int p1, int p2) {
if(x <= l && r <= y) {
(beg[rt][0] += p1) %= Mod, (beg[rt][1] += p2) %= Mod;
(tree[rt] += FibDelta(p1, p2, r - l + 1)) %= Mod;
val[rt] = 1;
return ;
} int mid = (l + r) >> 1;
pushdown(rt, l, r); if(y <= mid) modify(ls, x, y, p1, p2);
else if(mid + 1 <= x) modify(rs, x, y, p1, p2);
else {
modify(ls, x, mid, p1, p2); /**/
node z = FibForward((node){p1, p2}, mid - x);/**/
//F[i] -> F[i + mid - x]: p1 -> z.x, p2 -> z.y
modify(rs, mid + 1, y, z.x, z.y);/*The InterVal needs to move*/
}
pushup(rt);
}
int query(int rt, int l, int r, int x, int y) {
if(x <= l && r <= y) return tree[rt]; int mid = (l + r) >> 1; pushdown(rt, l, r); if(y <= mid) return query(ls, x, y);
else if(mid + 1 <= x) return query(rs, x, y);
else return (1ll * query(ls, x, y) + 1ll * query(rs, x, y)) % Mod;
}
#undef lc
#undef rc
#undef ls
#undef rs
}
namespace INIT {
void Main() {
n = read(), m = read(); f[1] = 1; f[2] = 1;
rep(i, 3, n + 4) f[i] = (f[i - 1] * 1ll + f[i - 2]) % Mod; rep(i, 1, n) a[i] = read(); SGMT_tree :: build(1, 1, n);
}
}
namespace SOLVE {
void Main() {
rep(i, 1, m) {
int opt = read(); if(opt == 1) {
int x = read(), y = read();
SGMT_tree :: modify(1, 1, n, x, y, 1, 1);
}
if(opt == 2) {
int x = read(), y = read();
write(SGMT_tree :: query(1, 1, n, x, y)), putchar('\n');
}
}
}
}
int main() {
freopen("CF446C.in", "r", stdin);
freopen("CF446C.out", "w", stdout); INIT :: Main();
SOLVE :: Main();
#ifdef Qrsikno
debug("\nRunning time: %.3lf(s)\n", clock() * 1.0 / CLOCKS_PER_SEC);
#endif
return IO.flush();
}

CF446C [DZY loves Fibonacci]的更多相关文章

  1. cf446C DZY Loves Fibonacci Numbers

    C. DZY Loves Fibonacci Numbers time limit per test 4 seconds memory limit per test 256 megabytes inp ...

  2. 【思维题 线段树】cf446C. DZY Loves Fibonacci Numbers

    我这种maintain写法好zz.考试时获得了40pts的RE好成绩 In mathematical terms, the sequence Fn of Fibonacci numbers is de ...

  3. CF446C DZY Loves Fibonacci Numbers 线段树 + 数学

    有两个性质需要知道: $1.$ 对于任意的 $f[i]=f[i-1]+f[i-2]$ 的数列,都有 $f[i]=fib[i-2]\times f[1]+fib[i-1]\times f[2]$ 其中 ...

  4. 「CF446C」 DZY Loves Fibonacci Numbers

    「CF446C」 DZY Loves Fibonacci Numbers 这里提供一种优美的根号分治做法. 首先,我们考虑一种不太一样的暴力.对于一个区间加斐波那契数的操作 \([a,b]\),以及一 ...

  5. codeforces 446C DZY Loves Fibonacci Numbers(数学 or 数论+线段树)(两种方法)

    In mathematical terms, the sequence Fn of Fibonacci numbers is defined by the recurrence relation F1 ...

  6. Codeforces 446-C DZY Loves Fibonacci Numbers 同余 线段树 斐波那契数列

    C. DZY Loves Fibonacci Numbers time limit per test 4 seconds memory limit per test 256 megabytes inp ...

  7. Codeforces Round #FF 446 C. DZY Loves Fibonacci Numbers

    參考:http://www.cnblogs.com/chanme/p/3843859.html 然后我看到在别人的AC的方法里还有这么一种神方法,他预先设定了一个阈值K,当当前的更新操作数j<K ...

  8. Codeforces446C - DZY Loves Fibonacci Numbers

    Portal Description 给出一个\(n(n\leq3\times10^5)\)个数的序列,进行\(m(m\leq3\times10^5)\)次操作,操作有两种: 给区间\([L,R]\) ...

  9. [CodeForces - 447E] E - DZY Loves Fibonacci Numbers

    E  DZY Loves Fibonacci Numbers In mathematical terms, the sequence Fn of Fibonacci numbers is define ...

随机推荐

  1. python执行

    转载:https://www.cnblogs.com/zflibra/p/4180796.html

  2. Asp.net core使用MediatR进程内发布/订阅

    1.背景 最近,一个工作了一个月的同事离职了,所做的东西怼了过来.一看代码,惨不忍睹,一个方法六七百行,啥也不说了吧,实在没法儿说.介绍下业务场景吧,一个公共操作A,业务中各个地方都会做A操作,正常人 ...

  3. GPIO简介

    GPIO(General Purpose I/O Ports)意思为通用输入/输出端口,通俗地说,就是一些引脚,可以通过它们输出高低电平或者通过它们读入引脚的状态-是高电平或是低电平. GPIO口一是 ...

  4. (void __user *)arg 中__user的作用

    __user宏简单告诉编译器(通过 noderef)不应该解除这个指针的引用(因为在当前地址空间中它是没有意义的). (void __user *)arg 指的是arg值是一个用户空间的地址,不能直接 ...

  5. 【转载】在VS2008中使用WSE 3.0过程全记录

    WSE全称是Web Service Enhancement,提供了更好的安全性实现,以及大对象传输的设计. 有关WSE的一些介绍,如果不清楚,可以参考下面的链接 官方介绍:http://www.mic ...

  6. Android签名机制之---签名验证过程具体解释

    一.前言 今天是元旦,也是Single Dog的嚎叫之日,仅仅能写博客来祛除寂寞了,今天我们继续来看一下Android中的签名机制的姊妹篇:Android中是怎样验证一个Apk的签名. 在前一篇文章中 ...

  7. 深度学习笔记之CNN(卷积神经网络)基础

    不多说,直接上干货! 卷积神经网络(ConvolutionalNeural Networks,简称CNN)提出于20世纪60年代,由Hubel和Wiesel在研究猫脑皮层中用于局部敏感和方向选择的神经 ...

  8. Java经常使用日期操作具体解释

    Date类型大多数时间分量计算方法已经被Calendar代替 Date经常用法setTime getTime() new Date();默认获取当前的时间 SimpleDateFormat用来格式化和 ...

  9. 百度接口通过ip获取用户所在地

    /** * 百度接口      * 通过用户ip获取用户所在地      * @param userIp      * @return      */ public static String get ...

  10. Java中去除字符串中的所有空格

    JAVA中去掉空格     1. String.trim()    trim()是去掉首尾空格         2.str.replace(" ", ""); ...