• SDOI 2016 Round1 Day2


    生成魔咒

    /*
    后缀数组+双向链表
    参照:https://blog.csdn.net/clove_unique/article/details/53911757
    */
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=1e5+5;
    int n,cnt,c[N],ans[N],s[N],t[N],rank[N],trank[N],sa[N],tsa[N],h[N],nxt[N],pre[N];
    long long res;
    void DA(){
        int p,maxx=cnt;
        memset(c,0,sizeof c);
        for(int i=1;i<=n;i++) c[rank[i]=s[i]]++;
        for(int i=1;i<=maxx;i++) c[i]+=c[i-1];
        for(int i=n;i;i--) sa[c[rank[i]]--]=i;
        trank[sa[1]]=p=1;
        for(int i=2;i<=n;i++){
            if(rank[sa[i]]!=rank[sa[i-1]]) p++;
            trank[sa[i]]=p;
        }
        for(int i=1;i<=n;i++) rank[i]=trank[i];
        for(int k=1;p<n;k<<=1,maxx=p){
            p=0;
            for(int i=n-k+1;i<=n;i++) tsa[++p]=i;
            for(int i=1;i<=n;i++) if(sa[i]>k) tsa[++p]=sa[i]-k;
            memset(c,0,sizeof c);
            for(int i=1;i<=n;i++) trank[i]=rank[tsa[i]];
            for(int i=1;i<=n;i++) c[trank[i]]++;
            for(int i=1;i<=maxx;i++) c[i]+=c[i-1];
            for(int i=n;i;i--) sa[c[trank[i]]--]=tsa[i];
            trank[sa[1]]=p=1;
            for(int i=2;i<=n;i++){
                if(rank[sa[i]]!=rank[sa[i-1]]||rank[sa[i]+k]!=rank[sa[i-1]+k]) p++;
                trank[sa[i]]=p;
            }
            for(int i=1;i<=n;i++) rank[i]=trank[i];
        } 
        for(int i=1,k=0;i<=n;i++){
            int j=sa[rank[i]-1];
            while(s[i+k]==s[j+k]) k++;
            h[rank[i]]=k;if(k>0) k--;
        }
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&s[i]),t[i]=s[i];
        for(int i=1;i<=n/2;i++) swap(s[i],s[n-i+1]);
        sort(t+1,t+n+1);
        cnt=unique(t+1,t+n+1)-(t+1);
        for(int i=1;i<=n;i++) s[i]=lower_bound(t+1,t+cnt+1,s[i])-t;
        DA();
        for(int i=1;i<=n;i++){
            nxt[i]=i+1;
            pre[i]=i-1;
        }
        for(int i=1;i<=n;i++){
            int k=rank[i];
            ans[i]=n-i+1-max(h[k],h[nxt[k]]);
            h[nxt[k]]=min(h[k],h[nxt[k]]);
            nxt[pre[k]]=nxt[k];
            pre[nxt[k]]=pre[k];
        }
        for(int i=n;i;i--){
            res+=ans[i];
            printf("%lld
    ",res);
        }
        return 0;
    }

    排列计数

    /*
    ans=C(n,m)*dp(n-m);|dp(i)表示i的错排数
    */
    #include<cstdio>
    using namespace std;
    typedef long long ll;
    inline ll read(){
        ll x=0;char ch=getchar();
        while(ch<'0'||ch>'9'){ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x;
    }
     
    #define FRE(name) freopen(#name".in","r",stdin);freopen(#name".out","w",stdout);
    #define fre(name) freopen(#name".txt","r",stdin);
    #ifdef WIN32
    #define LL "%I64d"
    #else
    #define LL "%lld"
    #endif
     
    const ll S=1e6;
    const ll N=S+5;
    const ll mod=1e9+7;
    ll cas,n,m,ans,dp[N],fz[N],fm[N];
    ll fpow(ll a,ll p){
        ll res=1;
        for(;p;p>>=1,a=a*a%mod) if(p&1) res=res*a%mod;
        return res;
    }
    void first(){
        dp[0]=1;dp[1]=0;
        fz[1]=fz[0]=fm[1]=fm[0]=1;
        for(ll i=2;i<=S;i++) dp[i]=(i*dp[i-1]%mod+((i&1)?-1:1)+mod)%mod;
        for(ll i=2;i<=S;i++) fz[i]=fz[i-1]*i%mod;
        fm[S]=fpow(fz[S],mod-2);
        for(ll i=S-1;i>=1;i--) fm[i]=fm[i+1]*(i+1)%mod;
    }
    void solve(){
        for(cas=read();cas--;){
            n=read();m=read();
            ans=(((fz[n]*fm[m])%mod*fm[n-m])%mod*dp[n-m])%mod;
            printf(LL "
    ",ans);
        }
    }
    int main(){
        //FRE(permutation);
        first();
        solve();
        return 0;
    }

    征途

    /*
    ans=m(x_1^2+X_2^2+……+x_m^2)-(x_1+X_2+……+x_m)^2
    令dp[i][j]表示前i个数已经选择到了x_j的最小值;这样就变成了一个区间dp
    我懒,就不写单调队列优化了
    */
    #include<cstdio>
    #include<cstring>
    using namespace std;
    typedef long long ll;
     
    #define pf(x) ((x)*(x))
    #define fro __attribute__((optimize("O2")))
    #define FRE(name) freopen(#name".in","r",stdin);freopen(#name".out","w",stdout);
    #define fre(name) freopen(#name".txt","r",stdin);
    #ifdef WIN32
    #define LL "%I64d"
    #else
    #define LL "%lld"
    #endif
     
    const int N=3005;
    int n,m,a[N],p[N][N];
    ll ans,sum[N],dp[N][N];
     
    fro int main(){
        //FRE(journey);
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]),sum[i]=sum[i-1]+a[i];
        memset(dp,0x3f3f3f3f,sizeof dp);
        dp[0][0]=0;
        for(int j=1;j<=m;j++){
            for(int i=j;i<=n;i++){
                for(int k=p[i-1][j];k<i;k++){
                    if(dp[i][j]>dp[k][j-1]+pf(sum[i]-sum[k])){
                        dp[i][j]=dp[k][j-1]+pf(sum[i]-sum[k]);
                        p[i][j]=k;
                    }
                }
            }
        }
        ans=dp[n][m]*(ll)m-pf(sum[n]);
        printf(LL,ans);
        return 0;
    }
    
  • 相关阅读:
    Android零基础入门第34节:Android中基于监听的事件处理
    【洛谷】3953:逛公园【反向最短路】【记忆化搜索(DP)统计方案】
    【洛谷】1608:路径统计 1144:最短路计数
    【洛谷】1081:跑路【倍增】【最短路】
    照着例子学习protobuf-python
    NodeJs与ActionScript的GET和POST通讯
    编程语言应用领域(转)
    我是C#上层转到嵌入式和单片机的
    转发一位老师的文章,希望能给你带来帮助
    沈逸的IT专栏博客记录
  • 原文地址:https://www.cnblogs.com/shenben/p/6403153.html
Copyright © 2020-2023  润新知