• 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——面向对象的程序设计——创建对象与继承
    JavaScript 引用类型
    JavaScript 变量、作用域和内存问题
    JavaScript基本概念——操作符
    JavaScript基本概念
    在HTML中使用JavaScript
    JavaScript简介
    记录前端遇到的坑
    第八次作业
    电脑上下载b站视频到本地
  • 原文地址:https://www.cnblogs.com/julyc/p/6440470.html
Copyright © 2020-2023  润新知