P13465 [GCJ 2008 #1C] Increasing Speed Limits题解
P13465 [GCJ 2008 #1C] Increasing Speed Limits
题目描述
你在高速公路上行驶时因超速被交警拦下。原来他们一直在跟踪你,他们惊讶地发现你一路都在加速,完全没有踩 f刹车!现在你急需一个借口来解释这一切。
你决定说:“我看到的所有限速标志都是递增的,所以我一直在加速。”警察听后大笑,并把你经过的这段高速公路上所有的限速标志都告诉了你,并表示你不太可能这么幸运,刚好只看到了一段递增的标志。
现在你需要估算这种情况发生的概率,换句话说,就是要找出给定序列中有多少个不同的严格递增子序列。空子序列不计入答案,因为那意味着你根本没看任何限速标志!
例如,(1,2,5)(1, 2, 5)(1,2,5) 是 (1,4,2,3,5,5)(1, 4, 2, 3, 5, 5)(1,4,2,3,5,5) 的一个递增子序列,并且我们要计数两次,因为有两种方式可以从原序列中选出 (1,2,5)(1, 2, 5)(1,2,5)。
输入格式
第一行输入一个整数 NNN,表示测试用例的数量。接下来有 NNN 组测试数据。每组测试数据的第一行为 nnn、mmm、XXX、YYY 和 ZZZ,用空格分隔。nnn 表示限速标志序列的长度,mmm 表示生成数组 AAA 的长度。接下来的 mmm 行,每行一个整数,依次为 A[0]A[0]A[0] 到 A[m−1]A[m-1]A[m−1]。
使用 AAA、XXX、YYY 和 ZZZ,按照如下伪代码生成限速标志序列。mod 表示取余操作。
for i = 0 to n-1
print A[i mod m]
A[i mod m] = (X * A[i mod m] + Y * (i + 1)) mod Z
注意:输入的生成方式仅用于减小输入文件的体积,与解题方法无关。
输出格式
对于每个测试用例,输出一行,格式为 “Case #TTT: SSS”,其中 TTT 表示测试用例编号,SSS 表示非空严格递增子序列的数量,对 1 000 000 0071\ 000\ 000\ 0071 000 000 007 取模。
输入输出样例 #1
输入 #1
2
5 5 0 0 5
1
2
1
2
3
6 2 2 1000000000 6
1
2
输出 #1
Case #1: 15
Case #2: 13
说明/提示
样例说明
对于第 222 个测试用例,限速标志序列应为 1,2,0,0,0,41, 2, 0, 0, 0, 41,2,0,0,0,4。
数据范围
- 1≤N≤201 \leq N \leq 201≤N≤20
- 1≤m≤1001 \leq m \leq 1001≤m≤100
- 0≤X≤1090 \leq X \leq 10^90≤X≤109
- 0≤Y≤1090 \leq Y \leq 10^90≤Y≤109
- 1≤Z≤1091 \leq Z \leq 10^91≤Z≤109
- 0≤A[i]<Z0 \leq A[i] < Z0≤A[i]<Z
小数据范围(15 分,测试点 1 - 可见)
- 1≤m≤n≤10001 \leq m \leq n \leq 10001≤m≤n≤1000
大数据范围(35 分,测试点 2 - 隐藏)
- 1≤m≤n≤5000001 \leq m \leq n \leq 5000001≤m≤n≤500000
由 ChatGPT 4.1 翻译
思路
树状数组维护DP。
代码见下
#include<bits/stdc++.h>
#define mod 1000000007
using namespace std;
long long t,n,m,x,y,z,a[1000005],b[500005],c[500005],a2[500005],db=0,f[500005],op=0;
map<long long,long long> mp;
inline long long lb(long long x){
return x&(-x);
}
inline void ci(long long x,long long v){
long long a1=x;
while(a1<=db){
a2[a1]=(a2[a1]+v)%mod;
a1=a1+lb(a1);
}
return ;
}
inline long long co(long long x){
long long a1=0;
while(x>=1){
a1=(a1+a2[x])%mod;
x-=lb(x);
}
return a1;
}
int main(){
cin>>t;
for(int o=1;o<=t;o++){
mp.clear();
cin>>n>>m>>x>>y>>z;
for(int i=0;i<=m-1;i++){
cin>>a[i];
}
for(int i=0;i<=n-1;i++){
b[i]=a[i%m];
c[i]=b[i];
a[i%m]=(x*a[i%m]+y*(i+1))%z;
}
db=1;
sort(c,c+n);
for(int i=0;i<=n-1;i++){
if(i==0||c[i]!=c[i-1]){
mp[c[i]]=++db;
}
}
for(int i=0;i<=n-1;i++){
b[i]=mp[b[i]];
}
for(int i=0;i<=db;i++){
a2[i]=0;
}
ci(1,1);
op=0;
for(int i=0;i<=n-1;i++){
f[i]=co(b[i]-1);
//cout<<a2[1]<<endl;
ci(b[i],f[i]);
op=(op+f[i])%mod;
}
cout<<"Case #"<<o<<": "<<op<<endl;
}
return 0;
}

浙公网安备 33010602011771号