Codeforces446C DZY Loves Fibonacci Numbers(线段树 or 分块?)

时间:2022-12-22 09:16:56

第一次看到段更斐波那契数列的,整个人都不会好了。事后看了题解才明白了一些。

首先利用二次剩余的知识,以及一些数列递推式子有下面的

Codeforces446C DZY Loves Fibonacci Numbers(线段树 or 分块?)

Codeforces446C DZY Loves Fibonacci Numbers(线段树 or 分块?)

Codeforces446C DZY Loves Fibonacci Numbers(线段树 or 分块?)

Codeforces446C DZY Loves Fibonacci Numbers(线段树 or 分块?)

Codeforces446C DZY Loves Fibonacci Numbers(线段树 or 分块?)

Codeforces446C DZY Loves Fibonacci Numbers(线段树 or 分块?)

至于怎么解出x^2==5(mod 10^9+9),我就不知道了,但是要用的时候可以枚举一下,把这些参数求出来之后就题目就可以转化为维护等比数列。

由于前面的常数可以最后乘,所以就等于维护两个等比数列好了。

下面我们来看如何维护一个等比数列。假如我对区间[L,R]的加上1,2,4,8...2^n的话,那么我只需要加一个标记x表示这个区间被加了多少次这样的2^n.

举个例子  [1,8] 上加一个等比数列,我只需要x+=1,就可以了,当我的区间往下传的时候,[1,4]这个区间的x+=1,[5,8]这个区间x+=2^4*1

这个利用的就是公比相同的数列相加仍然是等比数列的性质。求和利用的则是 a1(q^n-1)/(q-1),所以只需要预处理出q-1的逆元还有q^n我们就可以根据区间信息很快的求出和了。

在本题中 q-1的逆=q,首项也是q,所以前n项和就是 qi^(n+2)-qi^2(i=1,2). 其实主要就是考虑怎么维护等比数列的问题。

然后我看到在别人的AC的方法里还有这么一种神方法,他预先设定了一个阈值K,当当前的更新操作数j<K的时候,它就用一个类似于树状数组段更的方法,用一个 d数组去存内容,譬如它要在区间 [3,6]上加一段fibonacci

原来:

id 0 1 2 3 4 5 6 7 8 9 10

d  0 0 0 0 0 0 0 0 0 0 0

更新:

id 0 1 2 3 4 5 6  7  8  9 10

d  0 0 0 1 0 0 0 -5  -3 0 0

我们可以发现,当利用 d[i]=d[i]+d[i-1]+d[i-2] i由小到大更新后就会得到

id 0 1 2 3 4 5 6  7  8  9 10

d  0 0 0 1 1 2 3  0  0  0  0

所以对于[L,R]上加一段操作,我们可以d[L]+=1; d[R+1]-=f[R-L+2],d[R+2]=f[R-L+1];

所以假如我更新了m次,我每次更新的复杂度是O(1),我把所有数求出来一次的复杂度是O(n)

然后他的算法是这样的,j<K的时候更新的时候按照上述方法更新,询问的话则是将询问区间和更新的区间求交,把交的和加上去。

当j==K的时候,利用d还原出新的a,把当前的区间清0.

不难发现,复杂度应该为O(mn/K+mK),当mn/K=mK的时候取最小值,所以复杂度是O(mn^(1/2)).

然后由于CF可以承受10 ^8的运算,所以打个擦边球AC了。下面贴两份代码:

#pragma warning(disable:4996)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std; #define ll long long
#define mod 1000000009
#define maxn 300500
ll bas = 276601605;
ll q1 = 691504013;
ll q2 = 308495997; ll xx5 = 383008016;
ll inv5 = 200000002;
ll inv2 = 500000005; ll invq1;
ll invq2; ll pow_mod(ll a, ll n){
ll ret = 1;
while (n){
if (n & 1) ret = ret*a%mod;
n >>= 1;
a = a*a%mod;
}
return ret;
} ll a[maxn], b[maxn];
int n, m; ll val[maxn];
ll sum[maxn]; struct Node
{
int l, r;
ll ax, bx;
ll sum;
}N[maxn << 2]; void build(int i, int L, int R){
N[i].l = L; N[i].r = R;
N[i].ax = N[i].bx = N[i].sum = 0;
if (L == R){
return;
}
int M = (L + R) >> 1;
build(i << 1, L, M);
build(i << 1 | 1, M + 1, R);
} void pushDown(int i){
ll av = N[i].ax, bv = N[i].bx;
if (N[i].ax != 0 || N[i].bx != 0){
N[i << 1].ax = (N[i << 1].ax + av) % mod;
N[i << 1].bx = (N[i << 1].bx + bv) % mod;
int len = N[i << 1].r - N[i << 1].l + 1;
N[i << 1 | 1].ax = (N[i << 1 | 1].ax + av*a[len] % mod) % mod;
N[i << 1 | 1].bx = (N[i << 1 | 1].bx + bv*b[len] % mod) % mod;
int len2 = N[i << 1 | 1].r - N[i << 1 | 1].l + 1;
N[i << 1].sum = (N[i << 1].sum + av*(((a[len + 2] - a[2]) % mod + mod) % mod) % mod) % mod;
N[i << 1].sum = (N[i << 1].sum - bv*(((b[len + 2] - b[2]) % mod + mod) % mod) % mod) % mod;
N[i << 1 | 1].sum = (N[i << 1 | 1].sum + av*a[len] % mod*(a[len2 + 2] - a[2] + mod) % mod) % mod;
N[i << 1 | 1].sum = ((N[i << 1 | 1].sum - bv*b[len] % mod*(b[len2 + 2] - b[2] + mod) % mod) % mod + mod) % mod;
N[i].ax = N[i].bx = 0;
}
} void pushUp(int i){
N[i].sum = (N[i << 1].sum + N[i << 1 | 1].sum) % mod;
} void update(int i, int L, int R, ll x, ll y){
if (N[i].l == L&&N[i].r == R){
N[i].ax = (N[i].ax + x) % mod;
N[i].bx = (N[i].bx + y) % mod;
int len = R - L + 1;
N[i].sum = (N[i].sum + x*(a[len + 2] - a[2] + mod) % mod + mod) % mod;
N[i].sum = (N[i].sum - y*(b[len + 2] - b[2] + mod) % mod + mod) % mod;
return;
}
pushDown(i);
int M = (N[i].l + N[i].r) >> 1;
if (R <= M){
update(i << 1, L, R, x, y);
}
else if (L > M){
update(i << 1 | 1, L, R, x, y);
}
else{
int len = (M - L + 1);
update(i << 1, L, M, x, y);
update(i << 1 | 1, M + 1, R, a[len] * x%mod, b[len] * y%mod);
}
pushUp(i);
} ll query(int i, int L, int R){
if (N[i].l == L&&N[i].r == R){
return N[i].sum;
}
pushDown(i);
int M = (N[i].l + N[i].r) >> 1;
if (R <= M){
return query(i << 1, L, R);
}
else if (L > M){
return query(i << 1 | 1, L, R);
}
else{
return (query(i << 1, L, M) + query(i << 1 | 1, M + 1, R)) % mod;
}
pushUp(i);
} int main()
{
scanf("%d%d", &n, &m);
a[0] = b[0] = 1;
for (int i = 1; i <= n + 5; i++){
a[i] = a[i - 1] * q1%mod;
b[i] = b[i - 1] * q2%mod;
}
val[0] = 0; sum[0] = 0;
for (int i = 1; i <= n; i++){
scanf("%I64d", val + i);
sum[i] = (sum[i - 1] + val[i]) % mod;
}
build(1, 1, n);
int oper, l, r;
for (int i = 0; i < m; i++){
scanf("%d%d%d", &oper, &l, &r);
if (oper == 1) update(1, l, r, 1, 1);
else {
ll res = query(1, l, r);
res = (res + mod) % mod;
res = res*bas%mod;
res = (res + ((sum[r] - sum[l - 1]) % mod+mod)%mod) % mod;
printf("%I64d\n", res);
}
}
return 0;
}
#pragma warning(disable:4996)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <cmath>
#include <map>
#include <algorithm>
#include <queue>
using namespace std; #define ll long long
#define maxn 310000
#define K 800
#define mod 1000000009 ll a[maxn];
ll s[maxn];
ll f[maxn], g[maxn];
int n, m;
int kk;
ll d[maxn]; int l[K + 50], r[K + 50]; int main()
{
while (cin >> n >> m)
{
f[0] = 0; f[1] = 1; g[0] = 0; g[1] = 1;
for (int i = 2; i <= n+10; i++){
f[i] = (f[i - 1] + f[i - 2]) % mod;
g[i] = (g[i - 1] + f[i]) % mod;
}
s[0] = 0;
for (int i = 1; i <= n; i++){
scanf("%I64d", &a[i]);
s[i] = (s[i - 1] + a[i]) % mod;
}
memset(d, 0, sizeof(d));
int oper, li, ri;
kk = 0;
for (int i = 0; i < m; i++){
scanf("%d%d%d", &oper,&li,&ri);
if (oper == 1){
l[kk] = li, r[kk] = ri;
d[li] = (d[li] + 1) % mod;
d[ri + 1] = ((d[ri + 1] - f[ri - li + 2]) % mod + mod) % mod;
d[ri + 2] = ((d[ri + 2] - f[ri - li + 1]) % mod + mod) % mod;
kk++;
if (kk == K){
for (int i = 1; i <= n; i++){
if (i == 1) a[i] = (a[i] + d[i]) % mod;
else {
d[i] = (d[i] + d[i - 1] + d[i - 2]) % mod;
a[i] = (a[i] + d[i]) % mod;
}
s[i] = (s[i - 1] + a[i]) % mod;
}
memset(d, 0, sizeof(d));
kk = 0;
}
}
else{
ll res = ((s[ri] - s[li - 1]) % mod + mod) % mod;
for (int j = 0; j < kk; j++){
int lb = max(l[j], li);
int rb = min(r[j], ri);
if (lb <= rb){
res = (res + (g[rb - l[j] + 1] - g[lb - l[j]]) % mod + mod) % mod;
}
}
printf("%I64d\n", res);
}
}
}
return 0;
}

Codeforces446C DZY Loves Fibonacci Numbers(线段树 or 分块?)的更多相关文章

  1. ACM学习历程—Codeforces 446C DZY Loves Fibonacci Numbers&lpar;线段树 &amp&semi;&amp&semi; 数论&rpar;

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

  2. codeforces 446C DZY Loves Fibonacci Numbers 线段树

    假如F[1] = a, F[2] = B, F[n] = F[n - 1] + F[n - 2]. 写成矩阵表示形式可以很快发现F[n] = f[n - 1] * b + f[n - 2] * a. ...

  3. Codeforces 446C DZY Loves Fibonacci Numbers &lbrack;线段树,数论&rsqb;

    洛谷 Codeforces 思路 这题知道结论就是水题,不知道就是神仙题-- 斐波那契数有这样一个性质:\(f_{n+m}=f_{n+1}f_m+f_{n}f_{m-1}\). 至于怎么证明嘛-- 即 ...

  4. CF446C DZY Loves Fibonacci Numbers 线段树 &plus; 数学

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

  5. Codeforces446C - DZY Loves Fibonacci Numbers

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

  6. 『题解』Codeforces446C DZY Loves Fibonacci Numbers

    更好的阅读体验 Portal Portal1: Codeforces Portal2: Luogu Description In mathematical terms, the sequence \( ...

  7. codeforces 446C DZY Loves Fibonacci Numbers(数学 or 数论&plus;线段树)(两种方法)

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

  8. 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 ...

  9. 【思维题 线段树】cf446C&period; DZY Loves Fibonacci Numbers

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

随机推荐

  1. CentOS 6&period;5安装Oracle 11&period;2&period;0&period;4------CentOS 6&period;5安装

    规划: IP:192.168.213.199 mask: 255.255.255.0 gateway:192.168.213.1 DNS1:202.101.172.35 磁盘分区: 磁盘总大小:25G ...

  2. IE6&sol;IE7&sol;IE8兼容H5标签

    可以使用html5shiv(html5shiv主要解决HTML5提出的新元素不被IE6-8识别,这些新元素不能作为父节点包裹子元素,并且不能应用CSS样式)来解决 <!--[if lt IE 9 ...

  3. mysql远程连接命令&lpar;转&rpar;

    一.MySQL 连接本地数据库,用户名为"root",密码"123"(注意:"-p"和"123" 之间不能有空格) C: ...

  4. CSS中文字体对照表

    http://hotoo.googlecode.com/svn/trunk/labs/css/css-fonts.html CSS中文字体对照表 css字体名可以使用2种Unicode格式,以“微软雅 ...

  5. ASP&period;NET Page执行顺序【转】

    一.ASP.NET 母版页和内容页中的事件 母版页和内容页都可以包含控件的事件处理程序.对于控件而言,事件是在本地处理的,即内容页中的控件在内容页中引发事件,母版页中的控件在母版页中引发事件.控件事件 ...

  6. maven和jdk版本不匹配

    解决方法:http://blog.csdn.net/mafan121/article/details/51944346

  7. 深入ThreadLocal之二

    概述 相信读者在网上也看了很多关于ThreadLocal的资料,很多博客都这样说:ThreadLocal为解决多线程程序的并发问题提供了一种新的思路:ThreadLocal的目的是为了解决多线程访问资 ...

  8. getResourceAsStream和getResource的用法

    用JAVA获取文件,听似简单,但对于很多像我这样的新人来说,还是掌握颇浅,用起来感觉颇深,大家最经常用的,就是用JAVA的File类,如要取得 D:/test.txt文件,就会这样用File file ...

  9. 如何使用python timeit模块使用实践

    其实平时使用测试应用运行时间的情况 细算一下还真的很少.很久没有做性能优化的工作,不管是cProfile还是timeit模块都已经生疏了很久没有使用,我在以前的文章里面有提到过cPfile的性能测试使 ...

  10. 安装cmake 和 opencv 4&period;0&period;0

    1.安装cmake3.5.1或更新的版本 安装gcc-c++:sudo apt-get install build-essential (或者直接执行这两条命令sudo apt-get install ...