题意中文。
因为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")
#include<cstdio>
#include<ctype.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<cstdlib>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#include<ctime>
#include<string.h>
#include<string>
#include<sstream>
#include<bitset>
using namespace std;
#define ll long long
#define ull unsigned long long
#define eps 1e-11
#define NMAX 1000000005
#define MOD 1000000007
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define PI acos(-1)
template<class T>
inline void scan_d(T &ret)
{
char c;
int flag = 0;
ret=0;
while(((c=getchar())<'0'||c>'9')&&c!='-');
if(c == '-')
{
flag = 1;
c = getchar();
}
while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar();
if(flag) ret = -ret;
}
ll dp[19][2525][50];
int lcm[11][2525],biao[50],m[2525];
map<int,int>mp;
int gcd(int a,int b)
{
return (b == 0)?a:gcd(b,a%b);
}
void init()
{
for(int i = 0; i <= 9; i++)
for(int j = 1; j <= 2520; j++)
lcm[i][j] = i?i*j/gcd(i,j):j;
int nct = 1;
for(int i = 1; i <= 2520; i++) if(2520%i == 0)
{
m[i] = nct;
biao[nct++] = i;
}
biao[0] = 1;
// cout<<biao[48]<<endl;
}
char ch[25];
int main()
{
#ifdef GLQ
freopen("input.txt","r",stdin);
// freopen("o4.txt","w",stdout);
#endif // GLQ
init();
int cas;
scanf("%d",&cas);
while(cas--)
{
scanf("%s",ch);
int len = strlen(ch);
memset(dp,0,sizeof(dp));
for(int i = 0; i < ch[0]-'0'; i++)
dp[0][i][biao[i]] = 1;
int ha[2];
ha[0] = ha[1] = ch[0]-'0';
for(int i = 1; i < len; i++)
{
int p = (i==len-1)?ch[i]-'0'+1:ch[i]-'0';
for(int j = 0; j < p; j++)
dp[i][(ha[0]*10+j)%2520][m[lcm[j][ha[1]]]] = 1;
ha[0] = (ha[0]*10+p)%2520;
ha[1] = lcm[p][ha[1]];
int num = ch[i]-'0';
for(int j = 0; j < 2520; j++)
for(int k = 1; k <= 48; k++) if(dp[i-1][j][k])
{
ll d = dp[i-1][j][k];
for(int l = 0; l <= 9; l++)
{
int lc = m[lcm[l][biao[k]]];
// cout<<l<<" "<<lc<<" "<<lcm[l][biao[k]]<<endl;
dp[i][(j*10+l)%2520][lc] += d;
}
}
}
ll ans = 0;
for(int i = 0; i < 2520; i++)
for(int j = 1; j <= 48; j++)
{
if(i%biao[j] == 0) ans += dp[len-1][i][j];
}
if(len == 1) ans++;
ans--;
printf("%I64d\n",ans);
}
return 0;
}
AC代码2:
//#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<ctype.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<cstdlib>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#include<ctime>
#include<string.h>
#include<string>
#include<sstream>
#include<bitset>
using namespace std;
#define ll long long
#define ull unsigned long long
#define eps 1e-11
#define NMAX 1000005
#define MOD 1000000007
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define PI acos(-1)
template<class T>
inline void scan_d(T &ret)
{
char c;
int flag = 0;
ret=0;
while(((c=getchar())<'0'||c>'9')&&c!='-');
if(c == '-')
{
flag = 1;
c = getchar();
}
while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar();
if(flag) ret = -ret;
}
ll dp[20][2525][50];
int mp[2520],ha[50],lcm[11][2520],shu[20];
int gcd(int x, int y)
{
return y?gcd(y,x%y):x;
}
void init()
{
memset(dp,-1,sizeof(dp));
int nct = 1;
for(int i = 1; i <= 2520; i++) if(2520%i == 0)
{
ha[nct] = i;
mp[i] = nct++;
}
for(int i = 0;i <= 9; i++)
for(int j = 1; j <= 2520; j++)
lcm[i][j] = (i==0)?j:i*j/gcd(i,j);
}
ll dfs(int yu, int lc, int len,int limit)
{
if(len == 0)
return yu%ha[lc] == 0;
if(~dp[len][yu][lc] && !limit) return dp[len][yu][lc];
ll ans = 0;
int p = limit?shu[len]:9;
for(int i = p; i >= 0; i--)
{
ans += dfs((yu*10+i)%2520, mp[lcm[i][ha[lc]]],len-1, limit && i == shu[len]);
}
if(!limit) dp[len][yu][lc] = ans;
return ans;
}
int main()
{
#ifdef GLQ
freopen("input.txt","r",stdin);
// freopen("o4.txt","w",stdout);
#endif // GLQ
int cas;
ll n;
init();
scanf("%d",&cas);
while(cas--)
{
scanf("%I64d",&n);
int nct=1;
while(n)
{
shu[nct++] = n%10LL;
n /= 10LL;
}
// cout<<nct<<endl;
printf("%I64d\n",dfs(0,1,nct-1,1)-1);
}
return 0;
}