• 一本通 高手训练 1765 树上斐波那契 矩阵乘法 树链剖分


    LINK:树上斐波那契

    这道题关于广义斐波那契以及斐波那契的性质的一个题目。

    (f_a)表示斐波那契数列的第a项 那么有(f_{a+b}=f_{a-1}cdot f_b+f_{a}cdot f_{b+1})

    关于证明 可以采用数学归纳法。挺容易的。

    这道题是x子树内增加 (f_{k+D})其中k为常数 D为x子树内的点距x的距离。

    容易转换为 (f_{k+d_u-d_x}) 套上面的斐波那契类似于结论的等式就可以发现每次是单点增加定值可以直接维护和了。

    值得一提的是 由于k很大 所以需要矩阵乘法。

    还有就是 下表为负的情况 搞出广义斐波那契 使用即可。

    还是比较好码的题目。

    //#include<bitsstdc++.h>
    #include<iostream>
    #include<iomanip>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<ctime>
    #include<cmath>
    #include<cctype>
    #include<cstdlib>
    #include<queue>
    #include<deque>
    #include<stack>
    #include<vector>
    #include<algorithm>
    #include<utility>
    #include<bitset>
    #include<set>
    #include<map>
    #define ll long long
    #define db double
    #define INF 1000000000000000ll
    #define ldb long double
    #define pb push_back
    #define put_(x) printf("%d ",x);
    #define get(x) x=read()
    #define gt(x) scanf("%d",&x)
    #define gi(x) scanf("%lf",&x)
    #define put(x) printf("%d
    ",x)
    #define putl(x) printf("%lld
    ",x)
    #define gc(a) scanf("%s",a+1)
    #define rep(p,n,i) for(RE int i=p;i<=n;++i)
    #define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
    #define fep(n,p,i) for(RE int i=n;i>=p;--i)
    #define pii pair<int,int>
    #define mk make_pair
    #define RE register
    #define P 1000000007
    #define S second 
    #define F first
    #define gf(x) scanf("%lf",&x)
    #define pf(x) ((x)*(x))
    #define ull unsigned long long
    #define ui unsigned
    #define EPS 1e-8
    #define mod 1000000007
    #define sq sqrt
    #define zz p<<1
    #define yy p<<1|1
    #define l(p) t[p].l
    #define r(p) t[p].r
    #define sum(p) t[p].sum
    #define tag1(p) t[p].tag1
    #define tag2(p) t[p].tag2
    #define cnt1(p) t[p].cnt1
    #define cnt2(p) t[p].cnt2
    using namespace std;
    char buf[1<<15],*fs,*ft;
    inline char getc()
    {
        return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
    }
    inline int read()
    {
        RE int x=0,f=1;RE char ch=getc();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
        return x*f;
    }
    inline ll Read()
    {
        RE ll x=0,f=1;RE char ch=getc();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
        return x*f;
    }
    const int MAXN=100010;
    int n,m,cnt,id,len;
    int fa[MAXN],sz[MAXN],son[MAXN],d[MAXN],top[MAXN],pos[MAXN],dfn[MAXN];
    int lin[MAXN],ver[MAXN<<1],nex[MAXN<<1],f[MAXN],df[MAXN];
    ll a[2][2],cc[2][2];
    inline void add(int x,int y)
    {
    	ver[++len]=y;nex[len]=lin[x];lin[x]=len;
    	ver[++len]=x;nex[len]=lin[y];lin[y]=len;
    }
    struct wy//线段树
    {
    	int l,r;
    	int sum;
    	int cnt1,cnt2;
    	int tag1,tag2;
    }t[MAXN<<2];
    struct jl//FiB
    {
    	int f[2];
    	jl(){f[0]=0;f[1]=1;}
    	inline jl calc(ll w)
    	{
    		jl c;
    		a[0][0]=0;a[0][1]=a[1][0]=a[1][1]=1;
    		while(w)
    		{
    			if(w&1)
    			{
    				ll w1=0,w2=0;
    				w1=(w1+c.f[0]*a[0][0])%mod;
    				w2=(w2+c.f[0]*a[0][1])%mod;
    				w1=(w1+c.f[1]*a[1][0])%mod;
    				w2=(w2+c.f[1]*a[1][1])%mod;
    				c.f[0]=w1;c.f[1]=w2;
    			}
    			w=w>>1;
    			rep(0,1,i)rep(0,1,j)rep(0,1,k)
    				cc[i][j]=(cc[i][j]+a[i][k]*a[k][j])%mod;
    			rep(0,1,i)rep(0,1,j)a[i][j]=cc[i][j],cc[i][j]=0;
    		}
    		return c;
    	}
    }s,ww;
    inline void dfs(int x,int ff)
    {
    	fa[x]=ff;d[x]=d[ff]+1;sz[x]=1;
    	go(x)if(tn!=ff)
    	{
    		dfs(tn,x);
    		if(sz[tn]>sz[son[x]])son[x]=tn;
    		sz[x]+=sz[tn];
    	}
    }
    inline void dp(int x,int ff)
    {
    	top[x]=ff;dfn[x]=++id;pos[id]=x;
    	if(!son[x])return;
    	dp(son[x],ff);
    	go(x)if(tn!=son[x]&&tn!=fa[x])dp(tn,tn);
    }
    inline void build(int p,int l,int r)
    {
    	l(p)=l;r(p)=r;
    	if(l==r)
    	{
    		cnt1(p)=(cnt1(p)+f[d[pos[l]]-1])%mod;
    		cnt2(p)=(cnt2(p)+f[d[pos[l]]])%mod;
    		return;
    	}
    	int mid=(l(p)+r(p))>>1;
    	build(zz,l,mid);
    	build(yy,mid+1,r);
    	cnt1(p)=(cnt1(zz)+cnt1(yy))%mod;
    	cnt2(p)=(cnt2(zz)+cnt2(yy))%mod;
    }
    inline void pushdown(int p)
    {
    	tag1(zz)=(tag1(zz)+tag1(p))%mod;
    	tag1(yy)=(tag1(yy)+tag1(p))%mod;
    	tag2(zz)=(tag2(zz)+tag2(p))%mod;
    	tag2(yy)=(tag2(yy)+tag2(p))%mod;
    	sum(zz)=(sum(zz)+(ll)tag1(p)*cnt1(zz))%mod;
    	sum(yy)=(sum(yy)+(ll)tag1(p)*cnt1(yy))%mod;
    	sum(zz)=(sum(zz)+(ll)tag2(p)*cnt2(zz))%mod;
    	sum(yy)=(sum(yy)+(ll)tag2(p)*cnt2(yy))%mod;
    	tag1(p)=tag2(p)=0;
    }
    inline void change(int p,int l,int r)
    {
    	if(l<=l(p)&&r>=r(p))
    	{
    		tag1(p)=(tag1(p)+ww.f[0])%mod;
    		tag2(p)=(tag2(p)+ww.f[1])%mod;
    		sum(p)=(sum(p)+(ll)ww.f[0]*cnt1(p))%mod;
    		sum(p)=(sum(p)+(ll)ww.f[1]*cnt2(p))%mod;
    		return;
    	}
    	if(tag1(p)||tag2(p))pushdown(p);
    	int mid=(l(p)+r(p))>>1;
    	if(l<=mid)change(zz,l,r);
    	if(r>mid)change(yy,l,r);
    	sum(p)=(sum(zz)+sum(yy))%mod;
    }
    inline int ask(int p,int l,int r)
    {
    	if(l<=l(p)&&r>=r(p))return sum(p);
    	int mid=(l(p)+r(p))>>1;
    	if(tag1(p)||tag2(p))pushdown(p);
    	if(r<=mid)return ask(zz,l,r);
    	if(l>mid)return ask(yy,l,r);
    	return (ask(zz,l,r)+ask(yy,l,r))%mod;
    }
    inline int Task(int x,int y)
    {
    	int fx=top[x],fy=top[y];
    	int ans=0;
    	while(fx!=fy)
    	{
    		if(d[fx]<d[fy])swap(x,y),swap(fx,fy);
    		ans=(ans+ask(1,dfn[fx],dfn[x]))%mod;
    		x=fa[fx];fx=top[x];
    	}
    	if(d[x]<d[y])swap(x,y);
    	ans=(ans+ask(1,dfn[y],dfn[x]))%mod;
    	return ans;
    }
    int main()
    {
    	//freopen("1.in","r",stdin);
    	get(n);get(m);df[1]=1;f[1]=1;
    	rep(2,n,i)add(i,read()),f[i]=(f[i-2]+f[i-1])%mod,df[i]=(df[i-2]-df[i-1]+mod)%mod;
    	dfs(1,0);dp(1,1);build(1,1,n);
    	rep(1,m,i)
    	{
    		char ch=getc();
    		while(ch!='Q'&&ch!='U')ch=getc();
    		if(ch=='U')
    		{
    			int get(x);ll k;k=Read()-d[x];
    			if(k<=0)
    			{
    				ww.f[0]=df[-k];
    				if(k==0)ww.f[1]=f[1];
    				else ww.f[1]=df[-(k+1)];
    			}
    			else ww=s.calc(k);
    			change(1,dfn[x],dfn[x]+sz[x]-1);
    		}
    		else put(Task(read(),read()));
    	}
    	return 0;
    }
    
  • 相关阅读:
    AD域撤销域用户管理员权限方案
    域普通用户执行金蝶K/3权限不够解决方法
    redis安装windows+64位
    解决pycharm中no python interpreter configured问题
    python3报错---Error in sitecustomize; set PYTHONVERBOSE for traceback: NameError: name 'reload' is not defined
    python+robot+oracle:执行脚本时中文sql报错:UnicodeEncodeError: 'ascii' codec can't encode
    git-最简单的操作流程
    pycharm配置后执行RF脚本
    性能测试-jmeter基础5-设计数据自动递增
    性能测试-jmeter基础4-设置日期的递增参数demo
  • 原文地址:https://www.cnblogs.com/chdy/p/12852821.html
Copyright © 2020-2023  润新知