您的位置:首页 > 其它

hdu 5179 beautiful number

2016-04-13 19:54 246 查看

beautiful number

问题描述
令 A = \sum_{i=1}^{n}a_i * {10}^{n-i}(1\leq a_i \leq 9)A=∑​i=1​n​​a​i​​∗10​n−i​​(1≤a​i​​≤9)(nn为AA的位数)。若AA为“漂亮的数”当且仅当对于任意1 \leq i < n1≤i<n满足a[i] \geq a[i+1]a[i]≥a[i+1]且对于任意1 \leq i \leq n,i < j \leq n1≤i≤n,i<j≤n,满足a[i]a[i] mod a[j]=0a[j]=0(例如931是一个“漂亮的数”而87不是),求在区间[L,R][L,R](包含L和R)里“漂亮的数”的个数。

输入描述
第一行包含一个正整数TT(大约100),表示数据的组数。
接下来TT行,每行两个数$L,R(1 \leq L \leq R \leq {10}^{9})$。

输出描述
对于每组数据输出一个正整数表示“漂亮的数”的个数。

输入样例
2
1 11
999999993 999999999

输出样例
10
2

由于题目要求各数位从高到低值递减而且还要满足后面必为前面约数的条件,所以从1到1e9里面的数不会很多,可以直接打表过,打表代码太长就不贴了
还是使用数位dp解这道题较好,使用pre代表第len位的前一位数值,经过思考可以知道如果从高到低逐位实现前者为后者的约数,那么就能够满足任意后一位为前者的约数。还有高位可以不断取0,多开一个参数处理就好

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int dp[111][10];
int a[111];
int dfs(int len,int pre,int flag,int d)
{
if(len==-1) return 1;
if(!flag&&dp[len][pre]!=-1) return dp[len][pre];
int end=flag?a[len]:9;
int ans=0;
for(int i=0;i<=end;i++)
{
if(d==0||(i<=pre&&i!=0&&pre%i==0))
ans+=dfs(len-1,i,flag&&i==end,d||i);
}
if(!flag)
dp[len][pre]=ans;
return ans;
}
int cacu(int x)
{
int top=0;
while(x)
{
a[top++]=x%10;
x/=10;
}
return dfs(top-1,0,1,0);
}
int main()
{
memset(dp,-1,sizeof(dp));
int T;
for(scanf("%d",&T);T;T--)
{
int l,r;
scanf("%d%d",&l,&r);
printf("%d\n",cacu(r)-cacu(l-1));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: