X mod f(x)
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1568 Accepted Submission(s): 660
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 <= 10
9), 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.
Each test case has two integers A, B.
Output
For each test case, output only one line containing the case number and an integer indicated the number of x.
Sample Input
Sample Output
Author
WHU
Source
2012 Multi-University Training Contest 9
题意:
读懂f(x)之后,就是求一个区间内满足这样条件的数 x mod f(x) 有多少个。
思路:
数位dp,先预处理dp[i][j][k][p],i位 各个位数之和为j mod k余p 的数有多少个。
dp[i][j][k][p] 可以推导出dp[i+1][j+d][k][(p+d)modk]。
然后就是计算[0,X]的个数,设X=AnAn-1...Ai...A1,那么从高位往低位算,
算到第i位时,设前面的高位都与X相同,枚举f(x)可能的值,前面高位以及第i位mod f(x) 余r,
那么后面的数需满足 mod f(x) =( r==0?0:f(x)-r ) 才能满足x mod f(x) 为0了,依次累加便得到答案了。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#pragma comment (linker,"/STACK:102400000,102400000")
#define maxn 10005
#define MAXN 100005
#define mod 100000000
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-6
typedef long long ll;
using namespace std;
int n,m,ans,cnt,tot,flag;
int dp[11][82][82][82],dight[15];
void init()
{
int i,j,k,t,p,q;
for(i=0;i<=9;i++)
{
for(j=1;j<=81;j++)
{
dp[1][i][j][i%j]=1;
}
}
for(p=1;p<=9;p++)
{
for(i=0;i<=9*p;i++)
{
for(j=1;j<=81;j++)
{
for(k=0;k<j;k++)
{
for(q=0;q<=9;q++)
{
if(i+q<=81) dp[p+1][i+q][j][(k*10+q)%j]+=dp[p][i][j][k];
}
}
}
}
}
}
int solve(int x)
{
if(x==0) return 0;
int i,j,k,p,t,u,v,s=1,sum,y=x,res;
sum=cnt=0;
while(y)
{
sum+=y%10;
dight[++cnt]=y%10;
y/=10;
}
res=0;
if(x%sum==0) res++;
for(i=1;i<=cnt;i++)
{
u=dight[i];
sum-=u;
s*=10;
x/=10;
for(j=0;j<u;j++) // 枚举这一位
{
for(k=sum+j;k<=sum+j+(i-1)*9;k++) // 枚举总和即要取模的数
{
if(k==0) continue ;
int r=(x*s+j*(s/10))%k; // 前面的和mod k余r
if(r) r=k-r; // 后面的和需满足
if(i>1) res+=dp[i-1][k-sum-j][k][r];
else if(r==0) res++;
}
}
}
return res;
}
int main()
{
int i,j,k,t,test=0;
init();
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
ans=solve(m)-solve(n-1);
printf("Case %d: %d\n",++test,ans);
}
return 0;
}