• 2020 2.10


    https://file.floj.tech/export/1299

    t1

    按时间排序,发现如果后头的人比前头的人楼层高则前头的人莫得用,后面的人送上去时这个人必上去了。

    然后就可以得到一个楼层单调递减的序列,考虑f[i]表示前i个人送完最短时间。f[i]=max(f[j],t[i])+2*h[j+1],对f[j]<t[i]的最大的j用t[i]转移,f[j]>t[i]的用单调队列维护最小值即可。

    代码如下:

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    const int N=1e6+5;
    int n,dao,top,f[N],que[N];
    struct pigu
    {
        int t,h;
    }a[N],st[N];
    inline int read()
    {
        char c=getchar();
        int x=0,f=1;
        while(!isdigit(c)) {if(c=='-') f=-1;c=getchar();}
        while(isdigit(c)) {x=(x<<3)+(x<<1)+c-'0';c=getchar();}
        return x*f;
    }
    inline bool cmp(pigu x,pigu y)
    {
        return x.t<y.t;
    }
    signed main()
    {
    //    freopen("elevator.in","r",stdin);
    //    freopen("elevator.out","w",stdout);
        n=read();
        for(int i=1;i<=n;i++) a[i].t=read(),a[i].h=read();
        sort(a+1,a+n+1,cmp);
        for(int i=1;i<=n;i++)
        {
            while(top&&st[top].h<=a[i].h) top--;
            st[++top]=a[i];
        }
        int head=1,tail=0;
        for(int i=1;i<=top;i++)
        {
            while(dao<i-1&&f[dao+1]<=st[i].t) dao++;
            f[i]=st[i].t+st[dao+1].h*2;
            while(head<=tail&&f[que[head]]<=st[i].t) head++;
            if(head<=tail) f[i]=min(f[i],f[que[head]]+2*st[que[head]+1].h);
            while(head<=tail&&f[i]+2*st[i+1].h<=f[que[tail]]+2*st[que[tail]+1].h) tail--;
            que[++tail]=i;
        }
        cout<<f[top];
        return 0;
    }
    View Code

    t2

    矩阵快速幂。

    当T=0时就是求<=k的路径数,否则就是求疲劳值*路径数。

    用二项式定理将其拆开,y=1,构造(T+2)*n*(T+2)*n的矩阵即可。

    ans[i][j]表示从i出发走当前步数到j%n这个地方并且疲劳值的参数T=j/n时,路径数*疲劳值。

    转移矩阵大概kai[i][j]即为A[i%n][j%n]*C[j/n][i/n]。

    代码如下:

    #include<bits/stdc++.h>
    #define ll long long
    #pragma GCC optimize("Ofast") 
    using namespace std;
    const int N=492;
    const int mo=998244353;
    ll n,k,q,T,m,kais[75][75],C[9][9];
    struct matrix
    {
        ll ma[N][N];
         matrix operator *(const matrix &x) const
        {
            matrix z;memset(z.ma,0,sizeof(z.ma));
            for(int i=1;i<=m;++i)
            for(int k=1;k<=m;++k)if(ma[i][k])
            for(int j=1;j<=m;++j)if(x.ma[k][j])
            (z.ma[i][j]+=ma[i][k]*x.ma[k][j])%=mo;
            return z;
        }
    }kai,ans;
    inline ll read()
    {
        char c=getchar();
        int x=0,f=1;
        while(!isdigit(c)) {if(c=='-') f=-1;c=getchar();}
        while(isdigit(c)) {x=(x<<3)+(x<<1)+c-'0';c=getchar();}
        return x*f;
    }
    signed main()
    {
    //    freopen("road.in","r",stdin);
        //freopen("road.out","w",stdout);
        n=read();k=read();q=read();T=read();m=(T+2)*n;
        for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) kais[i][j]=read();
        for(int i=0;i<=T;i++) C[i][0]=1;
        for(int i=1;i<=T;i++)
            for(int j=1;j<=i;j++)
                C[i][j]=(C[i-1][j]+C[i-1][j-1]);
        for(int i=0;i<=T;i++)
            for(int j=i;j<=T;j++)
                for(int l=1;l<=n;l++)
                    for(int o=1;o<=n;o++)
                        kai.ma[i*n+l][j*n+o]=C[j][i]*kais[l][o]%mo;
        for(int i=1;i<=n;i++) ans.ma[i][i]=1;
        for(int i=1;i<=n;i++) kai.ma[T*n+i][T*n+n+i]=kai.ma[n*(T+1)+i][n*(T+1)+i]=1;
        while(k){if(k&1)ans=ans*kai;kai=kai*kai;k>>=1;}
        for(int i=1,x,y;i<=q;i++)
        {
            x=read();y=read();
            cout<<ans.ma[x][n*(T+1)+y]<<"
    ";
        }
    }
    View Code

    t3

    发现f就是一个k+1的多项式,所以g是k+2多项式,h是k+3多项式,使用拉格朗日插值求出前k+1,k+2,k+3项,就可以求第n项了。

    代码如下:

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    const int N=1105;
    int T,k,f1,f2,f3,n,a,d,mo,h[N],g[N],f[N],inv[N],pre[N],suf[N];
    inline int read()
    {
        char c=getchar();
        int x=0,f=1;
        while(!isdigit(c)) {if(c=='-') f=-1;c=getchar();}
        while(isdigit(c)) {x=(x<<3)+(x<<1)+c-'0';c=getchar();}
        return x*f;
    }
    inline int query(int * s,int len,int qiu)
    {
        int ans=0;
        if(qiu<=len) return s[qiu];
        for(int i=0;i<=len;i++)
            pre[i]=1ll*(qiu-i)*(i==0?1:pre[i-1])%mo;
        for(int i=len;i>=0;i--)
            suf[i]=1ll*(qiu-i)*(i==len?1:suf[i+1])%mo;
        for(int i=0;i<=len;i++)
        {
            int add=1ll*s[i]*(i==0?1:pre[i-1])%mo*(i==len?1:suf[i+1])%mo;
            add=1ll*add*inv[i]%mo*inv[len-i]%mo*(len-i&1?-1:1);
            ans=(ans+add)%mo+mo;
            ans%=mo;
        }
        return ans;
    }
    int qpow(int a,int b){
        int ans=1;
        for(;b;b>>=1,a=1ll*a*a%mo)
            if(b&1)ans=1ll*ans*a%mo;
        return ans;
    }
    signed main()
    {
        T=read();
        while(T--)
        {
            k=read();n=read();a=read();d=read();mo=read();
            f1=k+1;f2=k+2;f3=k+3;inv[0]=1;
            for(int i=1;i<=f3;++i)inv[i]=i==1?1:1ll*(mo-mo/i)*inv[mo%i]%mo;
            for(int i=1;i<=f3;++i)inv[i]=1ll*inv[i-1]*inv[i]%mo;
            for(int i=1;i<=f1;i++) 
            f[i]=(f[i-1]+qpow(i,k))%mo;
            cout<<query(f,f1,n)<<" ";
            for(int i=1;i<=f2;i++) g[i]=(g[i-1]+query(f,f1,i))%mo;
            cout<<query(g,f2,n)<<" ";
            for(int i=0;i<=f3;i++) 
                h[i]=query(g,f2,(1ll*i*d+a)%mo)+(i==0?0:h[i-1]),h[i]%=mo;
            cout<<query(h,f3,n)<<"
    ";
        }
    }
    View Code
  • 相关阅读:
    quotaon
    quotacheck
    quota
    query_module
    数据库连接驱动
    PHP 开发 APP 接口 学习笔记与总结
    Java实现 LeetCode 76 最小覆盖子串
    Java实现 LeetCode 74 搜索二维矩阵
    Java实现 LeetCode 74 搜索二维矩阵
    Java实现 LeetCode 74 搜索二维矩阵
  • 原文地址:https://www.cnblogs.com/betablewaloot/p/12305734.html
Copyright © 2020-2023  润新知