Description
有一个数列,它是由自然数组成的,并且严格单调上升。最小的数不小于S,最大的不超过T。现在知道这个数列有一个性质:后一个数相对于前一个数的增长率总是百分比下的整数(如5相对于4的增长率是25%,25为整数;而9对7就不行了)。现在问:这个数列最长可以有多长?满足最长要求的数列有多少个?
Input Format
输入仅有一行,包含S和T两个数( 0<S<T≤2000000<S<T≤200000 )。
30%的数据,0<S<T≤1000<S<T≤100 ;
100%的数据,0<S<T≤2000000<S<T≤200000。
Output Format
输出有2行。第一行包含一个数表示长度,第二行包含一个数表示个数。
Sample Input
2 10
Sample Output
5
2
样例解释
2 4 5 6 9以及2 4 5 8 10
代码:
#include <iostream>
using namespace std;
const int len = 200001;
int maxlen[len]; // 以i结尾的序列最长长度
long long maxTimes[len]; // 以i结尾的最长长度次数
long long countTimes[len] = {0}; // 长度为i的序列的个数
int main(int argc, char const *argv[]) {
int s, t, temp;
int maxlength = 1;
cin >> s >> t;
countTimes[1] = t - s + 1;
for(int i = s; i <= t; i++) {
maxlen[i] = 1;
maxTimes[i] = 1;
}
for(int i = s; i <= t; i++) {
for(int j = 1; j <= 100; j++) {
if((i * j) % 100 == 0){
temp = i + i * j / 100;
if(temp <= t){ // 在规定范围内
if(maxlen[temp] < maxlen[i] + 1) {
// 如果原来以temp结尾的序列最长长度比以i结尾的序列加上temp后的长度小
// 更新以temp结尾序列的最长长度
// 更新以temp结尾序列的最长长度次数
maxlen[temp] = maxlen[i] + 1;
maxTimes[temp] = maxTimes[i];
}
else if(maxlen[temp] == maxlen[i] + 1) {
// 如果原来以temp结尾的序列最长长度等于以i结尾的序列加上temp后的长度
// 最长长度不变,仅更新以temp结尾序列的最长长度次数
maxTimes[temp] += maxTimes[i];
}
// 找到最长长度
maxlength = maxlength > maxlen[temp] ? maxlength : maxlen[temp];
// 计算每一个长度下,序列出现的次数
countTimes[maxlen[i] + 1] += maxTimes[i];
}
}
}
}
cout << maxlength << endl << countTimes[maxlength] << endl;
return 0;
}
思路:
之前考虑的是遍历s到t去找哪些数符合要求,后发现循环层数过多会超时。参考了网上一个想法, 固定i为s到t间的值,通过对j进行1到100的循环遍历,来找到temp = i + i * j / 100,这个temp若在s到t的范围内,即符合要求,进行相应的记录(序列长度,长度出现次数)。
参考: