• QDC DAY1


      暴毙了,比较自闭的心理,有点崩溃..

    LINK:幸福 一道曾经的我肯定能写出来的 但是我心态崩了 所以没有推出来。

    当然 还是 我比较垃圾 但同时也不垃圾 。。。

    求 $T_n =displaystyle sum_{i=0}^{n}F_n$ 其中 $Fn=displaystyle sum_{i=0}^{n}f_i imes f_{n-i}$

    其中$f$是斐波那契数列 $f_0=1,f_1=1$... 求 $F_n$ 其中n<=1e18

     一个比较显然的思路是把Tn 写出来不断化简 最后发现是一个前缀和的形式 然后发现可以O(n)计算了。

    这样只有70分的垃圾成绩。

    //#include<bits/stdc++.h>
    #include<iomanip>
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<queue>
    #include<deque>
    #include<cmath>
    #include<ctime>
    #include<cstdlib>
    #include<stack>
    #include<algorithm>
    #include<vector>
    #include<cctype>
    #include<utility>
    #include<set>
    #include<bitset>
    #include<map>
    #define INF 1000000010
    #define ll long long
    #define mp(x,y) make_pair(x,y)
    #define un unsigned
    #define db double
    #define EPS 1e-5
    #define mod 998244353
    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 ll read()
    {
        ll x=0,f=1;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 ll MAXN=1000010;
    ll n;
    ll ans,sum;
    ll f[MAXN];
    signed main()
    {
        //freopen("1.in","r",stdin);
        n=read();
        f[0]=1;f[1]=1;
        for(ll i=2;i<=n;++i)f[i]=(f[i-1]+f[i-2])%mod;
        if(n<=20000)
        {
            for(ll i=0;i<=n;++i)
            {
                for(ll j=0;j<=i;++j)
                    ans=(ans+f[j]*f[i-j])%mod;
            }
            printf("%lld
    ",ans);
            return 0;
        }
        if(n<=1000000)
        {
            for(int i=0;i<=n;++i)sum=(sum+f[i])%mod;
            for(int i=0;i<=n;++i)
            {
                sum=((sum-f[n-i+1])+mod)%mod;
                ans=(ans+f[i]*sum%mod)%mod;
            }
            printf("%lld
    ",ans);
            return 0;
        }
        //考虑 100分 容斥还没有想好 自闭
        printf("%lld
    ",ans);
        return 0;
    }
    View Code

    继续思考如何优化 发现这个其实是倒三角求和 扩大两倍是不正确的 所以我当时 算2h然后弃疗了。思考方向不是太对。

    观察一下$F_n$这个式子。 简单的 化简成 $F_n=sum_{i=0}^{n-2f_i imes f_{n-i}+f_{n-1}f_1+f_n+f_0$

    比较显然的是 这个东西显然可以 化简为 $F_n=F_{n-1}+F_{n-2}+f_n$;

    //#include<bits/stdc++.h>
    #include<iomanip>
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<queue>
    #include<deque>
    #include<cmath>
    #include<ctime>
    #include<cstdlib>
    #include<stack>
    #include<algorithm>
    #include<vector>
    #include<cctype>
    #include<utility>
    #include<set>
    #include<bitset>
    #include<map>
    #define INF 1000000010
    #define mod 998244353
    typedef long long ll;
    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 ll read()
    {
        ll x=0,f=1;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 ll MAXN=6;
    ll n,m=5;
    struct wy
    {
        ll f[MAXN];
        ll b[MAXN][MAXN];
        wy(){memset(f,0,sizeof(f));memset(b,0,sizeof(b));}
        friend wy operator *(wy A,wy B)
        {
            wy tmp;
            for(ll i=1;i<=m;++i)
                for(ll j=1;j<=m;++j)
                    for(ll k=1;k<=m;++k)
                        tmp.b[i][j]=(tmp.b[i][j]+A.b[i][k]*B.b[k][j])%mod;
            for(int i=1;i<=m;++i)tmp.f[i]=A.f[i];
            return tmp;
        }
        friend wy operator -(wy A,wy B)
        {
            wy tmp;
            for(ll i=1;i<=m;++i)
                for(ll j=1;j<=m;++j)
                    tmp.f[i]=(tmp.f[i]+A.f[j]*B.b[j][i])%mod;
            for(int i=1;i<=m;++i)
                for(int j=1;j<=m;++j)tmp.b[i][j]=A.b[i][j];
            return tmp;
        }
        friend wy operator ^(wy A,ll p)
        {
            while(p)
            {
                if(p&1)A=A-A;
                A=A*A;
                p=p>>1;
            }
            return A;
        }
    }C;
    signed main()
    {
        //freopen("1.in","r",stdin);
        n=read();
        C.b[1][2]=1;C.b[2][1]=1;C.b[2][2]=1;C.b[2][4]=1;
        C.b[3][4]=1;C.b[4][3]=1;C.b[4][4]=1;C.b[3][5]=1;
        C.b[4][5]=1;C.b[5][5]=1;C.b[2][5]=1;
        C.f[1]=1;C.f[2]=2;C.f[3]=1;C.f[4]=2;C.f[5]=3;
        C=C^(n-1);
        printf("%lld
    ",C.f[m]);
        return 0;
    }
    View Code

     所以 就有了 矩阵乘法的优化 以后要敏感一点 或者从不同的方向推一下。

    LINK:树链刨分简单的树形dp但需要一些小细节。 当时 可能有一点点慌 所以 题目没怎么看的懂。

    想想当时还是比较蠢的。但是过后做法还是很容易就看出来的了。

    首先是代价的问题 这个进行 简单的树上差分即可解决。考虑 求答案 不知道哪个点是根。

    很好 那么 直接 就 直接一点 以 1 为根 那么答案 我们显然可以贪心的统计出来。

    考虑换根。这里值得注意的是 我们是将边权转点权了 看起来很不形象的样子其实可以直接放到边权上 不过那也应该是点权的样子存在着。

    直接换根吧 然后有一个细节 其实主要过程是 x 到 y的换根 这里维护一个最大值和次大值就是为了防止y是x的最大值什么的。

    还有一点是 换过根之后的话 x就光荣的成为了y的儿子了 在y 继续向下换根的过程中 y的最大值和 次大值应该要被x所更新。(重点 不要像我这个sb一样没注意到)

    当然这个swap是必要的qwq 。。因为 swap x y 是要把x变成y的儿子 再swap回来是为了保证原本的关系 因为x其他儿子还需要转移。

    //#include<bits/stdc++.h>
    #include<iomanip>
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<queue>
    #include<deque>
    #include<cmath>
    #include<ctime>
    #include<cstdlib>
    #include<stack>
    #include<algorithm>
    #include<vector>
    #include<cctype>
    #include<utility>
    #include<set>
    #include<bitset>
    #include<map>
    #define max(x,y) ((x)>(y)?(x):(y))
    #define INF 1000000010
    #define ll long long
    #define mp(x,y) make_pair(x,y)
    #define un unsigned
    #define db double
    #define EPS 1e-5
    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 ll read()
    {
        ll x=0,f=1;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 ll MAXN=1000010;
    ll n,len,m,sum,cnt;
    ll lin[MAXN],nex[MAXN<<1],ver[MAXN<<1];
    ll sz[MAXN],vis[MAXN],f[MAXN],s[MAXN],son[MAXN],sx[MAXN];
    struct wy
    {
        ll x,y,lca;
    }t[MAXN];
    vector<ll>g[MAXN],id[MAXN];
    inline void add(ll x,ll y)
    {
        ver[++len]=y;
        nex[len]=lin[x];
        lin[x]=len;
    }
    inline ll getfather(ll x){return x==f[x]?x:f[x]=getfather(f[x]);}
    inline void dfs(ll x)
    {
        vis[x]=1;f[x]=x;
        for(ll i=lin[x];i;i=nex[i])
        {
            ll tn=ver[i];
            if(vis[tn])continue;
            dfs(tn);
            f[tn]=x;
        }
        for(unsigned ll i=0;i<g[x].size();++i)
        {
            ll tn=g[x][i];
            ll ID=id[x][i];
            if(vis[tn])t[ID].lca=getfather(tn);
        }
    }
    inline void dfs(ll x,ll father)
    {
        f[x]=0;
        for(ll i=lin[x];i;i=nex[i])
        {
            ll tn=ver[i];
            if(tn==father)continue;
            dfs(tn,x);
            sz[x]+=sz[tn];
            if(sz[son[x]]<sz[tn])son[x]=tn;
            f[x]+=f[tn];
        }
        for(ll i=lin[x];i;i=nex[i])
        {
            ll tn=ver[i];
            if(tn==father)continue;
            if(son[x]==tn)continue;
            if(sz[sx[x]]<sz[tn])sx[x]=tn;
        }
        f[x]+=sz[son[x]];sum+=sz[x];
    }
    inline void dp(ll x,ll father)
    {
        for(ll i=lin[x];i;i=nex[i])
        {
            ll tn=ver[i];
            if(tn==father)continue;
            s[tn]=f[tn]-sz[son[tn]]+s[x]-f[tn];
            if(son[x]==tn)s[tn]=s[tn]-sz[tn]+sz[sx[x]];
            swap(sz[x],sz[tn]);
            if(sz[x]>sz[son[tn]])
            {
                sx[tn]=son[tn];
                son[tn]=x;
            }
            else if(sz[x]>sz[sx[tn]])sx[tn]=x;
            s[tn]+=sz[son[tn]];
            dp(tn,x);
            swap(sz[x],sz[tn]);
        }
    }
    signed main()
    {
        //freopen("1.in","r",stdin);
        //freopen("1.out","w",stdout);
        n=read();m=read();
        for(ll i=1;i<n;++i)
        {
            ll x,y;
            x=read();y=read();
            add(x,y);add(y,x);
        }
        for(ll i=1;i<=m;++i)
        {
            ll x,y;
            x=read();y=read();
            t[i]=(wy){x,y};
            if(x==y){t[i].lca=x;continue;}
            g[x].push_back(y);
            g[y].push_back(x);
            id[x].push_back(i);
            id[y].push_back(i);
        }
        dfs(1);
        for(ll i=1;i<=m;++i)
        {
            ++sz[t[i].x];++sz[t[i].y];
            --sz[t[i].lca];--sz[t[i].lca];
        }
        dfs(1,0);s[1]=f[1];
        dp(1,0);
        for(ll i=1;i<=n;++i)cnt=max(cnt,s[i]);
        printf("%lld
    ",sum-cnt);
        return 0;
    }
    View Code
  • 相关阅读:
    MATLAB中的SFunction的用法(C语言)
    OpenGL中的转换矩阵
    MATLAB读取和写入Excel文件
    一阶微分方程的求解
    三对角矩阵(Tridiagonal Matrices)的求法:Thomas Algorithm(TDMA)
    CarSim与Simulink联合仿真
    三次样条插值(Cubic Spline Interpolation)及代码实现(C语言)
    在Simulink中创建库
    轮胎的魔术公式(Magic Fomula)模型
    C#中的编译时的类型与运行时的类型
  • 原文地址:https://www.cnblogs.com/chdy/p/11619236.html
Copyright © 2020-2023  润新知