poj2282(组合数学,数位上的dp)

题意:

计算给定范围内0-9这些数出现的次数

题解:
组合数学方法即可算出,感觉dp太大材小用了。

给出解法,都在代码注释里头。

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<math.h>
using namespace std;
typedef __int64 lld;
const lld MOD=1000000007;
#define oo 0x3f3f3f3f
#define digit 66
int a[10],b[10];

void Cnt(int n)
{
    memset(b,0,sizeof b);
    int l,r=0,m,t=1;
    while(n)
    {
        //举个例子来说明一下内容,假设对于这个数1234
        //现在假设取到3这个数位
        l=n/10;//左边的数
        m=n%10;//这个位的数
        for(int i=0;i<=9;i++)
            b[i]+=l*t;//枚举  左边0-11总共12个即为l,因为没取到12所以右边的数都可以取到0-9刚好十个数即为t
        b[0]-=t;//零位的多算了看这个情况:0004,发现这位是零的话就多算了t
        for(int i=0;i<m;i++)
            b[i]+=t;//计算左边为12的时候,除了这个为为3时其他情况个位数都是能取到0-9
        b[m]+=r;//单独计算这个为去3时那么各位只能去0-4
        n/=10;//位数往左移动
        r+=t*m;//累加到达边界左边数的个数
        t*=10;//累加没到达边界左边数的个数
    }
}

int main()
{
    int n,m;
    while(scanf("%d %d",&m,&n)&&(m||n))
    {
        if(m>n)
            swap(m,n);
        Cnt(m);
        memcpy(a,b,sizeof a);
        Cnt(n+1);
        for(int i=0;i<9;i++)
            printf("%d ",b[i]-a[i]);
        printf("%d\n",b[9]-a[9]);
    }
	return 0;
}











你可能感兴趣的:(dp,poj)