D. Duff in Beach
题意 数字串a[0---n-1], 通过不断的重复组成了 b[0,---l-1]l<10^18,
让你计算出 长度小于等于k的最长非递减子序列,满足,取得第 i 个取得是 L1 第i+1个取得是L2 ------ L1/n +1 = L2, 通过这个我们先对原数组进行排序,排完后使用vector去计算dp[i][j]
及时 第i个数放在第j位的方案总数, 然后我们依次枚举放1 个 2 个3个。。。k, 贡献分别是 l/n,l/n-1....1,这样再枚举那最后的余下的那一些。
#include <iostream> #include <algorithm> #include <cstdio> #include <vector> #include <string.h> using namespace std; const int maxn=1000006; typedef long long LL; const LL mod=1000000007; int A[maxn],B[maxn],C[maxn],D[maxn],E[maxn]; vector<LL>G[maxn]; void init(int n,int k) { for(int i=0; i<=n; i++) { G[i].clear(); for(int j=0; j<=k; j++)G[i].push_back(0); } } int main() { int n,k;LL l; while(scanf("%d%I64d%d",&n,&l,&k)==3) { init(n,k); for(int i=0;i<n; i++) { scanf("%d",&A[i]); B[i]=A[i]; } sort(B,B+n); int ge=1; C[0]=1; for(int i=1; i<n;i++) { if(B[i]==B[ge-1])C[ge-1]++; else{ B[ge++]=B[i]; C[ge-1]=1; } } LL num=l/n; LL ans=l%mod; LL uu=min(k*1LL,num+1); int lest=l%n,numoflest=1; sort(A,A+lest); if(lest>0){ E[0]=1; for(int i=1; i<lest; i++) { if(A[i]==A[numoflest-1])E[numoflest-1]++; else{ A[numoflest++]=A[i]; E[numoflest-1]=1; } } } for(int i=0; i<ge; i++)G[i][1]=C[i]; for(int i=2; i<=k; i++) { long long d=0,S=0; int loc=0; for(int j=0; j<ge; j++) { d+=G[j][i-1]; d=d%mod; G[j][i]=(d*C[j])%mod; S=(S+G[j][i])%mod; while(loc<lest&&A[loc]<B[j])loc++; if(loc<lest && A[loc] == B[j]) { if(i<=uu) ans=(ans+(d*E[loc])%mod )%mod; } } if( num - i + 1 > 0 ) { long long gg=( S * ( ( num - i + 1 )%mod ) )%mod; ans=(ans+gg)%mod; } } printf("%I64d\n",ans); } return 0; }