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
原文地址:https://www.cnblogs.com/betablewaloot/p/12305734.html