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. 深度学习综述(LeCun、Bengio和Hinton)

    原文摘要:深度学习可以让那些拥有多个处理层的计算模型来学习具有多层次抽象的数据的表示.这些方法在很多方面都带来了显著的改善,包含最先进的语音识别.视觉对象识别.对象检測和很多其他领域,比如药物发现和基 ...

  2. 熊猫猪新系统測试之二:Mac OS X 10.10 优胜美地

    在第一篇windows 10技术预览版測试之后.本猫为大家呈现还有一个刚刚才更新的mac操作系统:"优胜美地".苹果相同一改以猫科动物为代号命名的传统.在10.9的Maverick ...

  3. BestCoder Round #2 1001 TIANKENG’s restaurant

    不得不说,bastcoder是个hack游戏啊.!. 题意:求最少要多少张椅子才干让全部来的客人有地方坐!! 就是一个区间的处理吧!!!和HDU  1556 我待水似流年.流年待我似水神似! ..! ...

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

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

  5. Windows 7旗舰版安装Visual Studio 2013 Ultimate的系统必备及注意事项

    系统必备: 1.Windows7 SP1 2.IE 10

  6. bzoj3109【CQOI2013】新数独

    3109: [cqoi2013]新数独 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 365  Solved: 229 [Submit][Statu ...

  7. (八)Java 修饰符

    Java 修饰符 Java语言提供了很多修饰符,主要分为以下两类: 访问修饰符 非访问修饰符 修饰符用来定义类.方法或者变量,通常放在语句的最前端.我们通过下面的例子来说明: public class ...

  8. mysql15--垂直分表水平分表

    分表技术(表的结构不能变) 分表技术有(水平分割和垂直分割) 当一张越来越大时候,即使添加索引还慢的话,我们可以使用分表 以qq用户表来具体的说明一下分表的操作. 思路如图 : 首先我创建三张表 u ...

  9. YTU 2436: C++ 习题 输出日期时间--友元类

    2436: C++ 习题 输出日期时间--友元类 时间限制: 1 Sec  内存限制: 128 MB 提交: 1243  解决: 690 题目描述 设计一个日期类和时间类,编写display函数用于显 ...

  10. POJ - 1330 Nearest Common Ancestors(dfs+ST在线算法|LCA倍增法)

    1.输入树中的节点数N,输入树中的N-1条边.最后输入2个点,输出它们的最近公共祖先. 2.裸的最近公共祖先. 3. dfs+ST在线算法: /* LCA(POJ 1330) 在线算法 DFS+ST ...