题目连接:http://codeforces.com/problemset/problem/55/Dios
Volodya is an odd boy and his taste is strange as well. It seems to him that a positive integer number is beautiful if and only if it is divisible by each of its nonzero digits. We will not argue with this and just count the quantity of beautiful numbers in given ranges.git
The first line of the input contains the number of cases t (1 ≤ t ≤ 10). Each of the next t lines contains two natural numbers li and ri (1 ≤ li ≤ ri ≤ 9 ·1018).测试
Please, do not use %lld specificator to read or write 64-bit integers in C++. It is preffered to use cin (also you may use %I64d).this
Output should contain t numbers — answers to the queries, one number per line — quantities of beautiful numbers in given intervals (from li to ri, inclusively).spa
1
1 9
9
1
12 15
2
题目大意:输入n,m,问你区间[n,m]内有多少个数能被它的不为0的位数整除
首先讲一下这道题用到的东西:
看一下下面的证实
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
左右相等,证实成立
接着看:
那么咱们就能够用上式中的x*n对num进行取余,记录其取余后的值,显然,1~9的最小公倍数2520是最合理的x*n。
而在逐位统计时,能够直接由前面位取余后的值来获得包含新一位的新数字取余后的值。
例如 RX(R是已知前面位取余后的值),那么Rx%2520 == (R*10+x)%2520。就不在此废话证了。
咱们使用记忆化搜索。
**dfs(len, num, lcm, flag)
len表示迭代的长度,
num为截止当前位的数对2520取余后的值。
lcm为截止当前位的全部数的最小公倍数。
flag表示当前数是否能够任意取值(对取值上限进行判断)**
则可用dp[len][num][lcm]来对其进行记录。
但lcm按2520取值根本开不下,因此对lcm进行离散化,由于lcm必定能够整除2520,因此将1~2520能够整除2520的数进行标记便可,测试后发现只有48个,知足当前状况。
看代码
#include<iostream> #include<cstdio> #include<cstring> #include<stdio.h> #include<string.h> #include<cmath> #include<math.h> #include<algorithm> #include<set> #include<queue> #include<map> typedef long long ll; using namespace std; const ll mod=1e9+7; const int maxn=1e8+10; const int maxk=100+10; const int maxx=1e4+10; const ll maxa=2520; #define INF 0x3f3f3f3f3f3f ll a[25],Hash[2550]; ll dp[25][50][2550]; ll gcd(ll n,ll m) { return m?gcd(m,n%m):n; } ll dfs(ll pos,bool limit,ll sum,ll lcm)//sum是当前位数对2520取余后的值,lam是当前位的最小公倍数 { if(pos==-1) { return sum%lcm==0; } if(!limit&&dp[pos][Hash[lcm]][sum]!=-1) return dp[pos][Hash[lcm]][sum]; int up=limit?a[pos]:9; ll ans=0; for(int i=0;i<=up;i++) { ans+=dfs(pos-1,limit&&i==up,(sum*10+i)%maxa,i?lcm*i/gcd(lcm,i):lcm); } if(!limit) dp[pos][Hash[lcm]][sum]=ans; return ans; } ll solve(ll n) { ll p=0; while(n) { a[p++]=n%10; n/=10; } return dfs(p-1,1,0,1); } int main() { ios::sync_with_stdio(false); memset(Hash,0,sizeof(Hash)); int cnt=0; for(int i=1;i<=maxa;i++) { if(maxa%i==0) Hash[i]=cnt++; } int t; memset(dp,-1,sizeof(dp)); cin>>t; while(t--) { ll n,m; cin>>n>>m; cout<<solve(m)-solve(n-1)<<endl; } return 0; }