fzuoj Problem 2179 chriswho
http://acm.fzu.edu.cn/problem.php?pid=2179
Problem 2179 chriswho
Accept: 57 Submit: 136 Time Limit: 10000 mSec Memory Limit : 327680 KB
Problem Description
Chriswho很喜欢数字,特别喜欢一种数字,它能整除它的每一位数字(如果该位是0当做能整除),比如说126这个数字他就很喜欢,因为126%1=126%2=126%6=0。为了让更多的人喜欢这样的数,他决定出一道这样的题目。求解1到n(包括1和n)之间有多少个这样的数字。
Input
第一行是一个整数t表示case数(不超过10组)。接下来t行,每行一个整数n(1<=n<=9*10^18)。
Output
输出t行,每行包括一个数字,表示满足条件的数字个数。
Sample Input
2 9 15
Sample Output
9 13
Source
FOJ有奖月赛-2014年11月分析:
因为1-9的lcm是2520,所以对于每一个数模2520,余数如果是自己的lcm的倍数那么就是。
所以dp[i][j][k]代表位数为i,模2520为j,lcm为k的数个数。
枚举后面加的数字g,用dp[i][j][k]去更新dp[i+1][(j*10+g)%2520][lcm(g,k)]。
还要注意一点lcm的个数只有48个,所以就可以开一个数组映射。
写了2种写法,递推写法因为有大量状态浪费速度相当慢。
DFS则快很多
AC代码:
1 //#pragma comment(linker, "/STACK:102400000,102400000") 2 #include<cstdio> 3 #include<ctype.h> 4 #include<algorithm> 5 #include<iostream> 6 #include<cstring> 7 #include<vector> 8 #include<cstdlib> 9 #include<stack> 10 #include<cmath> 11 #include<queue> 12 #include<set> 13 #include<map> 14 #include<ctime> 15 #include<string.h> 16 #include<string> 17 #include<sstream> 18 #include<bitset> 19 using namespace std; 20 #define ll long long 21 #define ull unsigned long long 22 #define eps 1e-11 23 #define NMAX 1000000005 24 #define MOD 1000000007 25 #define lson l,mid,rt<<1 26 #define rson mid+1,r,rt<<1|1 27 #define PI acos(-1) 28 template<class T> 29 inline void scan_d(T &ret) 30 { 31 char c; 32 int flag = 0; 33 ret=0; 34 while(((c=getchar())<'0'||c>'9')&&c!='-'); 35 if(c == '-') 36 { 37 flag = 1; 38 c = getchar(); 39 } 40 while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar(); 41 if(flag) ret = -ret; 42 } 43 ll dp[19][2525][50]; 44 int lcm[11][2525],biao[50],m[2525]; 45 map<int,int>mp; 46 int gcd(int a,int b) 47 { 48 return (b == 0)?a:gcd(b,a%b); 49 } 50 51 void init() 52 { 53 for(int i = 0; i <= 9; i++) 54 for(int j = 1; j <= 2520; j++) 55 lcm[i][j] = i?i*j/gcd(i,j):j; 56 int nct = 1; 57 for(int i = 1; i <= 2520; i++) if(2520%i == 0) 58 { 59 m[i] = nct; 60 biao[nct++] = i; 61 } 62 biao[0] = 1; 63 // cout<<biao[48]<<endl; 64 } 65 66 char ch[25]; 67 int main() 68 { 69 #ifdef GLQ 70 freopen("input.txt","r",stdin); 71 // freopen("o4.txt","w",stdout); 72 #endif // GLQ 73 init(); 74 int cas; 75 scanf("%d",&cas); 76 while(cas--) 77 { 78 scanf("%s",ch); 79 int len = strlen(ch); 80 memset(dp,0,sizeof(dp)); 81 for(int i = 0; i < ch[0]-'0'; i++) 82 dp[0][i][biao[i]] = 1; 83 int ha[2]; 84 ha[0] = ha[1] = ch[0]-'0'; 85 for(int i = 1; i < len; i++) 86 { 87 int p = (i==len-1)?ch[i]-'0'+1:ch[i]-'0'; 88 for(int j = 0; j < p; j++) 89 dp[i][(ha[0]*10+j)%2520][m[lcm[j][ha[1]]]] = 1; 90 ha[0] = (ha[0]*10+p)%2520; 91 ha[1] = lcm[p][ha[1]]; 92 int num = ch[i]-'0'; 93 for(int j = 0; j < 2520; j++) 94 for(int k = 1; k <= 48; k++) if(dp[i-1][j][k]) 95 { 96 ll d = dp[i-1][j][k]; 97 for(int l = 0; l <= 9; l++) 98 { 99 int lc = m[lcm[l][biao[k]]]; 100 // cout<<l<<" "<<lc<<" "<<lcm[l][biao[k]]<<endl; 101 dp[i][(j*10+l)%2520][lc] += d; 102 } 103 } 104 } 105 ll ans = 0; 106 for(int i = 0; i < 2520; i++) 107 for(int j = 1; j <= 48; j++) 108 { 109 if(i%biao[j] == 0) ans += dp[len-1][i][j]; 110 } 111 if(len == 1) ans++; 112 ans--; 113 printf("%I64d\n",ans); 114 } 115 return 0; 116 }
1 //#pragma comment(linker, "/STACK:102400000,102400000") 2 #include<cstdio> 3 #include<ctype.h> 4 #include<algorithm> 5 #include<iostream> 6 #include<cstring> 7 #include<vector> 8 #include<cstdlib> 9 #include<stack> 10 #include<cmath> 11 #include<queue> 12 #include<set> 13 #include<map> 14 #include<ctime> 15 #include<string.h> 16 #include<string> 17 #include<sstream> 18 #include<bitset> 19 using namespace std; 20 #define ll long long 21 #define ull unsigned long long 22 #define eps 1e-11 23 #define NMAX 1000005 24 #define MOD 1000000007 25 #define lson l,mid,rt<<1 26 #define rson mid+1,r,rt<<1|1 27 #define PI acos(-1) 28 template<class T> 29 inline void scan_d(T &ret) 30 { 31 char c; 32 int flag = 0; 33 ret=0; 34 while(((c=getchar())<'0'||c>'9')&&c!='-'); 35 if(c == '-') 36 { 37 flag = 1; 38 c = getchar(); 39 } 40 while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar(); 41 if(flag) ret = -ret; 42 } 43 ll dp[20][2525][50]; 44 int mp[2520],ha[50],lcm[11][2520],shu[20]; 45 46 int gcd(int x, int y) 47 { 48 return y?gcd(y,x%y):x; 49 } 50 51 void init() 52 { 53 memset(dp,-1,sizeof(dp)); 54 int nct = 1; 55 for(int i = 1; i <= 2520; i++) if(2520%i == 0) 56 { 57 ha[nct] = i; 58 mp[i] = nct++; 59 } 60 for(int i = 0;i <= 9; i++) 61 for(int j = 1; j <= 2520; j++) 62 lcm[i][j] = (i==0)?j:i*j/gcd(i,j); 63 } 64 65 ll dfs(int yu, int lc, int len,int limit) 66 { 67 if(len == 0) 68 return yu%ha[lc] == 0; 69 if(~dp[len][yu][lc] && !limit) return dp[len][yu][lc]; 70 ll ans = 0; 71 int p = limit?shu[len]:9; 72 for(int i = p; i >= 0; i--) 73 { 74 ans += dfs((yu*10+i)%2520, mp[lcm[i][ha[lc]]],len-1, limit && i == shu[len]); 75 } 76 if(!limit) dp[len][yu][lc] = ans; 77 return ans; 78 } 79 80 int main() 81 { 82 #ifdef GLQ 83 freopen("input.txt","r",stdin); 84 // freopen("o4.txt","w",stdout); 85 #endif // GLQ 86 int cas; 87 ll n; 88 init(); 89 scanf("%d",&cas); 90 while(cas--) 91 { 92 scanf("%I64d",&n); 93 int nct=1; 94 while(n) 95 { 96 shu[nct++] = n%10LL; 97 n /= 10LL; 98 } 99 // cout<<nct<<endl; 100 printf("%I64d\n",dfs(0,1,nct-1,1)-1); 101 } 102 return 0; 103 }
悠游天地间 all rights reserved. © 2013 -- 1 << 64