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 组测试数据。每组测试数据的第一行为 nnnmmmXXXYYYZZZ,用空格分隔。nnn 表示限速标志序列的长度,mmm 表示生成数组 AAA 的长度。接下来的 mmm 行,每行一个整数,依次为 A[0]A[0]A[0]A[m−1]A[m-1]A[m1]

使用 AAAXXXYYYZZZ,按照如下伪代码生成限速标志序列。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 201N20
  • 1≤m≤1001 \leq m \leq 1001m100
  • 0≤X≤1090 \leq X \leq 10^90X109
  • 0≤Y≤1090 \leq Y \leq 10^90Y109
  • 1≤Z≤1091 \leq Z \leq 10^91Z109
  • 0≤A[i]<Z0 \leq A[i] < Z0A[i]<Z

小数据范围(15 分,测试点 1 - 可见)

  • 1≤m≤n≤10001 \leq m \leq n \leq 10001mn1000

大数据范围(35 分,测试点 2 - 隐藏)

  • 1≤m≤n≤5000001 \leq m \leq n \leq 5000001mn500000

由 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;
}
posted @ 2025-11-17 21:20  bz02_2023f2  阅读(4)  评论(0)    收藏  举报  来源