X mod f(x)Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3550 Accepted Submission(s): 1389 Problem Description Here is a function f(x): int f ( int x ) { if ( x == 0 ) return 0; return f ( x / 10 ) + x % 10; }Now, you want to know, in a given interval [A, B] (1 <= A <= B <= 109), how many integer x that mod f(x) equal to 0.
Input The first line has an integer T (1 <= T <= 50), indicate the number of test cases. Output For each test case, output only one line containing the case number and an integer indicated the number of x.
Sample Input 2 1 10 11 20
Sample Output Case 1: 10 Case 2: 3
|
题意: f(x) 即 数x 各个位数之和, 题目要求 求从A到B 满足 x % f(x) == 0 的数的个数
思路: 按数位dp的套路, 需要先 确定一个dp数组,并且这个dp数组的每一个下标只能 确定唯一个数 x
这里dp数组为四维, dp[pos][sum][mod][res], pos位数,此数和为sum,对mod取模,取模得到的就结果为res
AC代码:
#include<cstdio>
#include<cstring>
using namespace std;
int dp[11][82][82][82]; // 这里的四维占空间较大,改变任意一维的大小都可能引起MLE
int a[15];
int dfs(int pos,int sum,int mod,int res,bool limit){
if(pos == -1) return res == 0 && sum == mod;
if(!limit && dp[pos][sum][mod][res] != -1) return dp[pos][sum][mod][res];
int up = limit ? a[pos] : 9;
int tmp = 0,sum_x,res_x;
for(int i = 0;i <= up;i ++){
sum_x = sum + i;
res_x = (res * 10 + i) % mod;
tmp += dfs(pos-1,sum_x,mod,res_x,limit && i == a[pos]);
}
if(!limit) dp[pos][sum][mod][res] = tmp;
return tmp;
}
int slove(int x){
int pos = 0;
while(x){
a[pos ++] = x % 10;
x /= 10;
}
int ans = 0;
for(int i = 1;i <= 81;i ++) //枚举 模
ans += dfs(pos-1,0,i,0,true);
return ans;
}
int main()
{
int t; scanf("%d",&t);
memset(dp,-1,sizeof(dp));
int f = 1,n,m;
while(~scanf("%d%d",&n,&m)){
printf("Case %d: %d\n",f++,slove(m)-slove(n-1));
}
return 0;
}