Increasing Speed Limite HDU 3030
题意
给你一个长度为m的数组A,你可以通过给的X,Y,Z计算获得一个长度为n的数组,问你这个n长的序列有多少个非空严格上升序列。
思路
dp
- (dp[i]): 以第i个元素为结尾的非空严格上升序列个数
- (dp[i] =sum_{j=1}^{i-1}{dp[j]}+1), 其中 (a[j]<a[i])
- (ans = sum_{i=1}^n{dp[i]})
- 用树状数组求前缀和
代码
#include<bits/stdc++.h>
using namespace std;
#define lowbit(x) (x&(-x));
typedef long long ll;
const int MAXN=500005;
const int MOD= 1000000007;
int n,m;
ll X,Y,Z;
int A[MAXN],a[MAXN],b[MAXN];
ll c[MAXN];
void update(int x,ll value){
while(x<=n){
c[x]=(c[x]+value)%MOD;
x+=lowbit(x);
}
}
ll getSum(int x){
ll ret=0;
while(x){
ret=(ret+c[x])%MOD;
x-=lowbit(x);
}
return ret;
}
int main(){
// freopen("in.txt","r",stdin);
int T;
scanf("%d",&T);
for(int kase=1;kase<=T;kase++){
scanf("%d%d%lld%lld%lld",&n,&m,&X,&Y,&Z);
memset(c,0,sizeof(c));
for(int i=0;i<m;i++)
scanf("%d",&A[i]);
for(int i=0;i<n;i++){
a[i+1]=b[i+1]=A[i%m];
A[i%m]=(X*A[i%m]+Y*(i+1))%Z;
}
sort(a+1,a+n+1);
int an=unique(a+1,a+n+1)-a-1;
int p;
ll ans=0;
ll tmp=0;
for(int i=1;i<=n;i++){
p=lower_bound(a+1,a+an+1,b[i])-a;
tmp=getSum(p-1)+1;
ans=(ans+tmp)%MOD;
update(p,tmp);
}
printf("Case #%d: %lld
",kase,ans);
}
return 0;
}