zoukankan      html  css  js  c++  java
  • codeforces#588D

       看到题面就会想到传统的二维dp搞,但是原字符长度有1e18所以得另想办法。

      根据题目条件可以观察到:

      如果按照i/n的值分组的话,满足条件的子序列中的元素必定会在一段连续的组中

      同时每组元素种类数量都一样,这样我们就可以使用dp[len][i]得到长度为len,以每组中第i大元素结尾的种类数量

      然后长度为len的且以组中第i大元素结尾的答案数为dp[len][i]*(l/n-i+1)(l%n==0的情况,另外还有l%n!=0的情况得另行处理)

      这样对dp过程中对统计答案求和即可

     

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define ll long long
     4 #define inf 0x3f3f3f3f
     5 #define LL 2*n
     6 #define RR 2*n+1
     7 #define lson l,mid,LL
     8 #define rson mid+1,r,RR
     9 #define mid (l+r)/2
    10 #define pb push_back
    11 #define mp make_pair
    12 #define pii pair<int,int>
    13 #define mit map<int,int>::iterator
    14 #define sit set<int>::iterator
    15 #define vit vector<int>::iterator
    16 #define mii map<int,int>
    17 #define si set<int>
    18 #define vi vector<int>
    19 #define mod 1000000007
    20 const int maxn=2000005;
    21 struct node
    22 {
    23     ll x,idx;
    24 };
    25 bool cmp(node x,node y)
    26 {
    27     if(x.x==y.x) 
    28     return x.idx<y.idx;
    29     return x.x<y.x;
    30 }
    31 ll dp[2][maxn],sum[2][maxn],b[maxn];
    32 node a[maxn];
    33 int main()
    34 {
    35     ll n,l,k;
    36     scanf("%I64d%I64d%I64d",&n,&l,&k);
    37     for(int i=1;i<=n;i++)
    38     {
    39         scanf("%I64d",&a[i].x);
    40         a[i].idx=i;
    41     }
    42     sort(a+1,a+1+n,cmp);
    43     for(int i=n;i>=1;i--)
    44     {
    45         if(i==n)
    46         {
    47             b[i]=n;
    48             continue;
    49         }
    50         if(a[i].x==a[i+1].x)
    51         b[i]=b[i+1];
    52         else
    53         b[i]=i;
    54     }
    55     for(int i=1;i<=n;i++)
    56     sum[1][i]=1;
    57     ll ans=0,now=0,nxt=1;
    58     for(ll i=1;i<=k;i++)
    59     {
    60         if(l/n-i+1<0)
    61         break;
    62         for(ll j=1;j<=n;j++)
    63         {
    64             dp[now][j]=sum[nxt][b[j]];
    65             sum[now][j]=(sum[now][j-1]+dp[now][j])%mod;
    66             ll tmp=l/n-i+1;
    67             if(a[j].idx<=l%n)
    68                 tmp++;
    69             ans=(ans+tmp%mod*dp[now][j]%mod)%mod;
    70         }
    71         swap(nxt,now);
    72     }
    73     printf("%I64d",ans);
    74     return 0;
    75 }
  • 相关阅读:
    JavaScript操作符instanceof揭秘
    Linux打开txt文件乱码的解决方法
    Working copy locked run svn cleanup not work
    poj 2299 UltraQuickSort 归并排序求解逆序对
    poj 2312 Battle City 优先队列+bfs 或 记忆化广搜
    poj2352 stars 树状数组
    poj 2286 The Rotation Game 迭代加深
    hdu 1800 Flying to the Mars
    poj 3038 Children of the Candy Corn bfs dfs
    hdu 1983 Kaitou Kid The Phantom Thief (2) DFS + BFS
  • 原文地址:https://www.cnblogs.com/julyc/p/6440470.html
Copyright © 2011-2022 走看看