題目連接: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; }