CodeForces 932B Recursive Queries_前缀和
CodeForces 932B Recursive Queries
我们定义两个函数f和g在正整数上.
其中f(n)=n的每一位非零数字的乘积,例如,n=1230,f(n) = 1*2*3。
当n<10时,g(n) = n.
其他情况,g(n) = g(f(n)).
你需要处理Q个询问,每个询问中,会给你三个整数l,r,k.你需要输出[l..r]中使得g(x)=k的x的个数。
Input第一行包含一个整数Q(1<=Q<=2*10^5).
接下来的Q行,每行三个整数l,r,k(1<=l<=r<=10^6,1<=k<=9).
Output对于每一个询问,输出一个对应答案。样例
Input
4
22 73 9
45 64 6
47 55 7
2 62 4
Output
1
4
0
8
Input
4
82 94 6
56 67 4
28 59 9
39 74 4
Output
3
1
1
5
f(x)打表。g(x)直接写。
查询不能用for(int i = l; i <= r; ++i)因为多组测试一层,for一层,g函数递归一层,一定会爆时间。所以要把查询过程的复杂度优化为O(1)。需要用前缀和。
声明一个二维前缀和数组sum[i][j],表示第i个数及之前的g(x) = j的数有多少个。
前缀和数组打表。由前一个数推下一个,类似递推。
for(int i = 0; i < N; ++i) for(int j = 0; j < 10; ++j) { if(j == g(i)) sum[i][j] += sum[i-1][j]+1; else sum[i][j] += sum[i-1][j]; }
还要注意查询时第n个数到m个数时,应该用sum[m][j]-sum[n-1][j]。
AC代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <cstdio> 3 4 using namespace std; 5 6 const int N = 1e6+10; 7 8 int f[N]; 9 int sum[N][10]; 10 11 void init() 12 { 13 for(int i = 10; i < N; ++i) 14 { 15 int mul = 1; 16 int j = i; 17 while(j != 0) 18 { 19 if((j%10) != 0) 20 mul *= j%10; 21 j /= 10; 22 } 23 f[i] = mul; 24 } 25 } 26 27 int g(int i) 28 { 29 if(i < 10) 30 return i; 31 return g(f[i]); 32 } 33 34 int main() 35 { 36 #ifdef local 37 freopen("in.txt","r",stdin); 38 #endif // local 39 init(); 40 int n; 41 cin >> n; 42 for(int i = 0; i < N; ++i) 43 for(int j = 0; j < 10; ++j) 44 { 45 if(j == g(i)) 46 sum[i][j] += sum[i-1][j]+1; 47 else 48 sum[i][j] += sum[i-1][j]; 49 } 50 while(n--) 51 { 52 int cnt = 0; 53 int l, r, k; 54 cin >> l >> r >> k; 55 cout << sum[r][k]-sum[l-1][k] << endl; 56 } 57 return 0; 58 }