CodeForces 55D Beautiful numbers (数位dp+搜索)★

来源:互联网 发布:英语听力怎么练 知乎 编辑:程序博客网 时间:2024/06/06 01:13

题意:统计某段区间内满足它所有非零数位能整除这个数本身的数的个数。

解法;

  自己搞的时候除了想到开N维数组分别记录之外没什么别的想法><

  2~9所有数的lcm最大是2520,dp[pos][pre_mod][pre_lcm]记录前pos位数对2520取余为pre_mod并且非零位的lcm位pre_lcm的个数。

  因为2到9的lcm最多只有不到50个,我们需要对lcm离散化一下。。。。

#include <set>#include <map>#include <stack>#include <queue>#include <deque>#include <cmath>#include <vector>#include <string>#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>using namespace std;#define L(i) i<<1#define R(i) i<<1|1#define INF  0x3f3f3f3f#define pi acos(-1.0)#define eps 1e-9#define maxn 10010#define MOD 1000000007const int mod = 2520;long long dp[25][2600][50];int Hash[2600],bit[25];long long n,m;void init(){    int cnt = 0;    for(int i = 1; i <= 2520; i++)        if(2520 % i == 0)            Hash[i] = ++cnt;}int gcd(int a,int b){    for(int r = a % b; r; a = b,b = r,r = a%b);    return b;}int lcm(int a,int b){    return a / gcd(a,b) * b;}long long dfs(int pos,int pre_mod,int pre_lcm,int flag){    if(!pos)        return pre_mod % pre_lcm == 0;    if(flag && dp[pos][pre_mod][Hash[pre_lcm]] >= 0)        return dp[pos][pre_mod][Hash[pre_lcm]];    int u = flag?9:bit[pos];    long long ans = 0;    for(int i = 0; i <= u; i++)    {        int next_mod = (pre_mod*10 + i) % mod;        int next_lcm = pre_lcm;        if(i)            next_lcm = lcm(next_lcm,i);        ans += dfs(pos-1,next_mod,next_lcm,flag||i < u);    }    if(flag)        dp[pos][pre_mod][Hash[pre_lcm]] = ans;    return ans;}long long solve(long long x){    int len = 0;    while(x)    {        bit[++len] = x % 10;        x /= 10;    }    return dfs(len,0,1,0);}int main(){    int t,C = 1;    scanf("%d",&t);    memset(dp,-1,sizeof(dp));    init();    while(t--)    {        scanf("%lld%lld",&n,&m);        printf("%lld\n",solve(m)-solve(n-1));    }    return 0;}


0 0