前缀和的应用 CodeForces - 932B Recursive Queries

题目链接:

https://vjudge.net/problem/1377985/origin

题目大意就是要你把一个数字拆开,然后相乘。

要求得数要小于9,否则递归下去。

这里用到一个递归函数:

int f(int x)
{
    if(x < 10) return x;
    int ans = 1;
    while(x)
    {
        if(x%10 != 0) ans *= x%10;
        else ans *= 1;
        x /= 10;
    }
    return f(ans);
}

这个函数用来求得一个数字最终得到的那个k值是多少。

然后开一个二元数组记录一下,并且用到了前缀和,统计从1开始k值出现的次数:(打表)

void get_table()
{
    for(int i = 1; i <= MX; ++i) mp[i][f(i)]++;
    for(int i = 1; i <= MX; ++i)
        for(int j = 1; j <= 9; ++j)
            mp[i][j] += mp[i-1][j];
}

最后,得到代码如下:(AC代码)

#include <iostream>
#include <cstdio>

using namespace std;
const int MX = 1e6+10;
int mp[MX][10];

int f(int x) //递归求值
{
    if(x < 10) return x;
    int ans = 1;
    while(x)
    {
        if(x%10 != 0) ans *= x%10;
        else ans *= 1;
        x /= 10;
    }
    return f(ans);
}

void get_table() //打表求值
{
    for(int i = 1; i <= MX; ++i) mp[i][f(i)]++;
    for(int i = 1; i <= MX; ++i)
        for(int j = 1; j <= 9; ++j)
            mp[i][j] += mp[i-1][j];
}

int main()
{
    get_table();
    int T;
    scanf("%d", &T);
    while(T--)
    {
        int le, ri, k;
        scanf("%d%d%d", &le, &ri, &k);
        int ans = mp[ri][k] - mp[le-1][k]; //left减一的理由是从le开始包括le, 若不减一的话left也会被减掉!
        printf("%d\n", ans);
    }
    return 0;
}
View Code

如有疑问,欢迎评论!

猜你喜欢

转载自www.cnblogs.com/mpeter/p/10290296.html