Online Judge——1012. 增长率问题(c++)

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的范围内,即符合要求,进行相应的记录(序列长度,长度出现次数)。

参考:

http://www.cnblogs.com/yuchenlin/p/sjtu_oj_1012.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值