hdu 4389 X mod f(x) (数位DP)

来源:互联网 发布:君君的淘宝店 编辑:程序博客网 时间:2024/05/16 17:00

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 <= 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.
   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
21 1011 20
 

Sample Output
Case 1: 10Case 2: 3
 

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-6typedef 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;}








 
0 0
原创粉丝点击