题解:
我们考虑题目条件,相当于n个一段,连续k段中满足条件的子序列个数
枚举起始段是哪段,然后把n*k个数存下来,很容易DP
这个DP是dp[i]=∑(dp[j]) a[j]<=a[i],j在i的前一段
复杂度的话每段丢进树状数组,然后结束再删掉就好了
前面的重复段算一下有多少个,然后乘一下就好
但是这样会有点问题,就是到k段中包含最后一段(不满n个的那段)会需要每次都重新DP,这部分一共要O(k*n*k)的复杂度,不能接受
我们反着枚举
枚举结束段是哪段,然后同理DP,这边a[j]>=a[i]
结束段是最后一段时DP一次,是其他段时DP一次
但同样的问题,开头的段怎么办
开头部分直接利用其它段时DP的那次的结果,统计其中1~k-1段的答案即可(因为是整段,所以直接利用答案)
1 #include<bits/stdc++.h> 2 #define maxn 1000005 3 #define ll long long 4 using namespace std; 5 const ll mod = 1000000007; 6 ll n,k,l; 7 ll a[maxn]; 8 ll m,p,q; 9 ll b[maxn],d; 10 ll c[maxn]; 11 ll f[maxn],g[maxn],ans; 12 struct BIT 13 { 14 ll a[maxn]; 15 void clear() 16 { 17 memset(a,0,sizeof(a)); 18 } 19 void add(int x,ll v) 20 { 21 for(;x<=maxn-5;x+=x&(-x))a[x]=(a[x]+v+mod)%mod; 22 } 23 ll get(int x) 24 { 25 ll ans=0; 26 for(;x;x-=x&(-x))ans=(ans+a[x])%mod; 27 return ans; 28 } 29 }tr; 30 int main() 31 { 32 scanf("%I64d%I64d%I64d",&n,&l,&k); 33 for(int i=1;i<=n;++i)scanf("%d",&a[i]),b[i]=a[i]; 34 sort(b+1,b+n+1); 35 d=unique(b+1,b+n+1)-b-1; 36 for(int i=1;i<=n;++i)a[i]=lower_bound(b+1,b+d+1,a[i])-b; 37 m=l/n;p=l%n; 38 if(!p)m--,p+=n; 39 q=max(0ll,m-k+1); 40 q%=mod; 41 int cnt=0; 42 for(int i=1;i<=k-1;++i) 43 for(int j=1;j<=n;++j)c[++cnt]=a[j]; 44 for(int i=1;i<=p;++i)c[++cnt]=a[i]; 45 for(int i=cnt-p+1;i<=cnt;++i)f[i]=1,tr.add(c[i],f[i]); 46 for(int i=k-1;i;--i) 47 { 48 for(int j=1;j<=n;++j) 49 { 50 int pos=(i-1)*n+j; 51 f[pos]=(tr.get(maxn-5)-tr.get(c[pos]-1)+mod)%mod; 52 } 53 for(int j=1;j<=n;++j) 54 { 55 int pos=(i-1)*n+j; 56 if(pos+n<=cnt)tr.add(c[pos+n],-f[pos+n]); 57 tr.add(c[pos],f[pos]); 58 } 59 } 60 for(int i=max(cnt-p-m*n+1,1ll);i<=cnt;++i)ans=(ans+f[i])%mod; 61 memset(c,0,sizeof(c)); 62 tr.clear(); 63 cnt=0; 64 for(int i=1;i<=k;++i) 65 for(int j=1;j<=n;++j)c[++cnt]=a[j]; 66 for(int i=cnt-n+1;i<=cnt;++i)g[i]=1,tr.add(c[i],g[i]); 67 for(int i=k-1;i;--i) 68 { 69 for(int j=1;j<=n;++j) 70 { 71 int pos=(i-1)*n+j; 72 g[pos]=(tr.get(maxn-5)-tr.get(c[pos]-1)+mod)%mod; 73 } 74 for(int j=1;j<=n;++j) 75 { 76 int pos=(i-1)*n+j; 77 tr.add(c[pos+n],-g[pos+n]); 78 tr.add(c[pos],g[pos]); 79 } 80 } 81 ll tmp=0; 82 for(int i=1;i<=min(m,k-1);++i) 83 { 84 for(int j=1;j<=n;++j) 85 { 86 int pos=(k-i)*n+j; 87 tmp=(tmp+g[pos])%mod; 88 } 89 ans=(ans+tmp)%mod; 90 } 91 tmp=0; 92 for(int i=1;i<=k;++i) 93 for(int j=1;j<=n;++j) 94 { 95 int pos=(i-1)*n+j; 96 tmp=(tmp+g[pos])%mod; 97 } 98 tmp=tmp*q%mod; 99 ans=(ans+tmp)%mod; 100 printf("%I64d ",ans); 101 return 0; 102 }