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 }
View Code

 

  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 }
View Code

 

你可能感兴趣的:(em)