Skip to content

11012: 【原1012】增长率问题

题目

题目描述

author: 刘勤 原OJ链接:https://acm.sjtu.edu.cn/OnlineJudge-old/problem/1012

Description

有一个数列,它是由自然数组成的,并且严格单调上升。最小的数不小于S,最大的不超过T。现在知道这个数列有一个性质:后一个数相对于前一个数的增长率总是百分比下的整数(如5相对于4的增长率是25%,25为整数;而9对7就不行了)。现在问:这个数列最长可以有多长?满足最长要求的数列有多少个?

Input Format

输入仅有一行,包含S和T两个数( \( 0 < S < T \leq 200000 \) )。

30%的数据,\( 0 < S < T \leq 100 \) ;

100%的数据,\( 0 < S < T \leq 200000 \)。

Output Format

输出有2行。第一行包含一个数表示长度,第二行包含一个数表示个数。

Sample Input

2 10

Sample Output

5
2

样例解释

2 4 5 6 9以及2 4 5 8 10

FineArtz's solution

/* 增长率问题 */
#include <iostream>
#include <cmath>
#include <vector>
using namespace std;

vector<int> CanInc[200005];
int len[200005] = {0};
long long tms[200005] = {0}, cnt[200005] = {0};
//f[i]表示以i结尾的最长序列长度tms[i]表示以i结尾的最长序列的个数cnt[i]表示长度为i的序列数

/*void PreTreatment(int s, int t){
    for (int i = s; i != t; ++i)
        for (int p = 1; p <= 99; ++p){
            if (trunc(s * p * 0.01) == (s * p / 100))
                CanInc[i].push_back(p);
        }
}
*/
int main(){
    int s, t;
    cin >> s >> t;
    for (int i = s; i <= t; ++i){
        len[i] = 1;
        tms[i] = 1;
    }
    cnt[1] = t - s + 1;
    long long ans = 1;
    for (int i = s; i < t; ++i){
        for (int j = 1; j <= 100; ++j){
            if (i * j % 100 == 0){
                int next = i + i * j / 100;
                if (next > t) continue;
                if (len[next] == len[i] + 1){
                    tms[next] += tms[i];
                }
                else if (len[next] < len[i] + 1){
                    len[next] = len[i] + 1;
                    tms[next] = tms[i];
                }
                ans = (ans > len[next] ? ans : len[next]);
                cnt[len[i] + 1] += tms[i];
            }
        }
    }
    cout << ans << endl;
    cout << cnt[ans] << endl;
    return 0;
}

ligongzzz's solution

#include "iostream"
#include "cstring"
#include "cstdio"
using namespace std;

long long dp_data[500009] = { 0 };
long long cal_num[500009] = { 0 };

long long dp(long long num, long long T) {
    if (dp_data[num] > 0)
        return dp_data[num];
    if (num > T) {
        return 0;
    }

    long long ans = 0;
    for (long long i = 1; i <= 100; ++i) {
        if (num * i % 100 == 0) {
            long long cur_ans = dp(num * i / 100 + num, T) + 1;
            ans = cur_ans > ans ? cur_ans : ans;
        }
    }
    for (long long i = 1; i <= 100; ++i) {
        if (num * i % 100 == 0) {
            if (dp_data[num + num * i / 100] + 1 == ans) {
                cal_num[num] += cal_num[num + num * i / 100];
            }
        }
    }
    if (ans == 1)
        cal_num[num] = 1;
    dp_data[num] = ans;
    return ans;
}

int main() {
    long long S, T;
    cin >> S >> T;

    long long ans = 0;
    for (long long i = S; i <= T; ++i) {
        long long cur_ans = dp(i, T);
        ans = cur_ans > ans ? cur_ans : ans;
    }

    long long cnt = 0;
    for (long long i = S; i <= T; ++i) {
        if (dp(i, T) == ans) {
            cnt += cal_num[i];
        }
    }

    cout << ans << endl << cnt;

    return 0;
}

yyong119's solution

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;

const int maxn = 200007;
int d[maxn];
long long cnt[maxn], times[maxn];

int main() {

    int s, t;
    cin >> s >> t;
    memset(cnt, 0, sizeof(cnt));
    int tmp, ans = 1;
    cnt[1] = t - s + 1;

    for (int i = s; i <= t; ++i) d[i] = times[i] = 1;

    for (int i = s; i <= t; ++i) 
        for (int j = 1; j <= 100; ++j)
            if ((i*j)%100 == 0) {
                tmp = i + i * j / 100;
                if (tmp <= t) {
                    if(d[i] + 1 > d[tmp]) {
                        d[tmp] = d[i] + 1;
                        times[tmp] = times[i];
                    }
                    else if(d[i] + 1 == d[tmp]) times[tmp] += times[i];
                    ans = max(ans, d[tmp]);
                    cnt[d[i] + 1] += times[i]; 
                }
            } 
    cout << ans << endl << cnt[ans];    
    return 0;
}