标签:ace click gif lap net += 技术分享 blank namespace
题目链接:
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; }
如有疑问,欢迎评论!
前缀和的应用 CodeForces - 932B Recursive Queries
标签:ace click gif lap net += 技术分享 blank namespace
原文地址:https://www.cnblogs.com/mpeter/p/10290296.html