zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    HDU 5583 Kingdom of Black and White 水题
    HDU 5578 Friendship of Frog 水题
    Codeforces Round #190 (Div. 2) E. Ciel the Commander 点分治
    hdu 5594 ZYB's Prime 最大流
    hdu 5593 ZYB's Tree 树形dp
    hdu 5592 ZYB's Game 树状数组
    hdu 5591 ZYB's Game 博弈论
    HDU 5590 ZYB's Biology 水题
    cdoj 1256 昊昊爱运动 预处理/前缀和
    cdoj 1255 斓少摘苹果 贪心
  • 原文地址:https://www.cnblogs.com/betablewaloot/p/12305734.html
Copyright © 2011-2022 走看看