CodeForces

来源:互联网 发布:复杂网络节点介数 编辑:程序博客网 时间:2024/06/11 14:45






A - Beautiful numbers

 CodeForces - 55D 

参考了

http://www.cnblogs.com/kuangbin/archive/2013/05/01/3052670.html


http://blog.csdn.net/to_be_better/article/details/50658392

        

Beautiful numbers指:一个数能整除所有组成它的非0数字。
等同于 一个数能整除 所有组成它的非0数字的最小公倍数。
我们看到数据的范围是1 ≤ li ≤ ri ≤ 9 ·1018,根本无法记录。
所以,缩小范围成为第一要做的事。
先看一个小式子。

    sum%(x*n)%x == sum%x;证明:设sum = k*x+b    等号左边:        sum%(x*n)%x -> (k*x+b)%(x*n)%x         将k转为ka*n + kb代入;        (ka*n*x+kb*x+b)%(x*n)%x -> (kb*x+b)%x -> b%x -> b    等号右边:        b左右相等,证明成立

所以可以将数字先mod1~9的最小公倍数 2520 又因为1~9组合组合出来lcm在1~2520里只有48个

#include <iostream>#include <algorithm>#include <cstring>#include <cstdio>#include <cmath>using namespace std;const int MOD=2520;long long dp[20][2550][50];//位数 mod2520后的值 各数位的最小公倍数lcmint n,m,t;int index[MOD+10],bit[20];//lcm存的位置long long l,r;int gcd(int a,int b){    if (b==0) return a;    return gcd(b,a%b);}long long dfs(int len,int psum,int plcm,int flag){    if (len==-1) {      if (psum%plcm==0) return 1;else return 0;    }    if (!flag&&dp[len][psum][index[plcm]]!=-1) return dp[len][psum][index[plcm]];    int end=flag?bit[len]:9;    long long ans=0;    for (int i=0;i<=end;++i){        ans+=dfs(len-1,(psum*10+i)%MOD,i?plcm*i/gcd(plcm,i):plcm,flag&&i==end);    }    if (!flag) dp[len][psum][index[plcm]]=ans;    return ans;}long long slove(long long n){    int len=0;    while (n){        bit[len++]=n%10;        n/=10;    }    return dfs(len-1,0,1,1);}int main(){    int cnt=0;    memset(dp,-1,sizeof(dp));    for (int i=1;i<=MOD;++i){        if (MOD%i==0) index[i]=cnt++;    }    scanf("%d",&t);    while (t--){        scanf("%lld%lld",&l,&r);        printf("%lld\n",slove(r)-slove(l-1));    }}






















0 0
原创粉丝点击