看到题面就会想到传统的二维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 }