表了一下,发现\(dig\)有值的数大概只有几万个,可以考虑做做。
然后发现它要\(gcd<=K\),考虑分解质因数后\(DP\)。然后不会。
考虑\(DP\),显然对答案有贡献的数位可以拆分成质因子。
设\(f[x][0/1][a][b][c][d]\)表示当前到了第\(x\)位,是否有顶格,\(gcd\)为\(2^a*3^b*5^c*7^d\)的方案数。
显然可以用数位\(DP\)转移,转移不讲。
设\(g[a][b][c][d]\)表示\(f[0][a][b][c][d]+f[1][a][b][c][d]\)
我们发现可以通过高维前缀和然后容斥来解决问题。
设\(g\)为后缀和后的\(g\),设\(h\)为两两间\(gcd\)为\(2^a*3^b*5^c*7^d\)的方案数。\(Solution\ 1\)\(h[a][b][c][d]\)显然可以用容斥来解决。\(h[a][b][c][d]=g[a][b][c][d]^2-g[a+1][b][c][d]^2-g[a][b+1][c][d]^2-g[a][b][c+1][d]^2-g[a][b][c][d+1]^2+......\)
当然这种写法十分的麻烦(吧)
\(Solution\ 2\)
高维前缀和以后,设\(p[a][b][c][d]\)表示\(h\)的后缀和
那么可以惊奇地发现:\(p\)=\(g*g\)!!!
是的,就是这么的神奇,求出\(p\)以后在逆推回去就得到\(h\)了。
答案就是把所有\(<=gcd\)的方案数加起来。。。
\(Code(Solution\ 2)\)
这数位\(DP\)和高维前缀和真是累死人不偿命。。。
#include <cstdio>
#include <cstring>
#define mo 998244353
#define db double
#define ll long long
#define mem(x, a) memset(x, a, sizeof x)
#define mpy(x, y) memcpy(x, y, sizeof y)
#define fo(x, a, b) for (int x = (a); x <= (b); x++)
#define fd(x, a, b) for (int x = (a); x >= (b); x--)
#define go(x) for (int p = tail[x], v; p; p = e[p].fr)
#define plus(x, y) x = x + y >= mo ? x + y - mo : x + y
#define nplus(x, y) x = x + mo - y >= mo ? x - y : x + mo - y
using namespace std;
const int fen[10][4] = {{0, 0, 0, 0}, {0, 0, 0, 0},
{1, 0, 0, 0}, {0, 1, 0, 0},
{2, 0, 0, 0}, {0, 0, 1, 0},
{1, 1, 0, 0}, {0, 0, 0, 1},
{3, 0, 0, 0}, {0, 2, 0, 0}};
int f[61][39][27][23], g[61][39][27][23], len, ans = 0;
int las_[4];
ll n, K, cf[19], cf0[4][60];
bool nonono = 0;
int get_len(ll x) {
int s = 0; while (x) s++, x /= 10;
cf[0] = 1; fo(i, 1, s) cf[i] = cf[i - 1] * 10;
return s;
}
int main()
{
freopen("lover.in", "r", stdin);
freopen("lover.out", "w", stdout);
scanf("%lld%lld", &n, &K);
len = get_len(n);
int fir_ = n / cf[len - 1] % 10;
fo(i, 1, fir_ - 1) f[fen[i][0]][fen[i][1]][fen[i][2]][fen[i][3]] = 1;
fo(i, 0, 3) las_[i] = fen[fir_][i];
cf0[0][0] = cf0[1][0] = cf0[2][0] = cf0[3][0] = 1;
fo(i, 1, 59) cf0[0][i] = cf0[0][i - 1] << 1;
fo(i, 1, 37) cf0[1][i] = cf0[1][i - 1] * 3;
fo(i, 1, 25) cf0[2][i] = cf0[2][i - 1] * 5;
fo(i, 1, 21) cf0[3][i] = cf0[3][i - 1] * 7;
fo(i, 2, len) {
int val = n / cf[len - i] % 10;
if (val == 0) nonono = 1;
mpy(g, f); mem(f, 0);
fo(j, 0, 59) {
if (cf0[0][j] > cf[i - 1]) break;
fo(k, 0, 37) {
if (cf0[0][j] * cf0[1][k] > cf[i - 1]) break;
fo(l, 0, 25) {
if (cf0[0][j] * cf0[1][k] * cf0[2][l] > cf[i - 1]) break;
fo(p, 0, 21) {
if (cf0[0][j] * cf0[1][k] * cf0[2][l] * cf0[3][p] > cf[i - 1]) break;
if (! g[j][k][l][p]) continue;
fo(q, 1, 9) {
if (j + fen[q][0] > 59 || k + fen[q][1] > 37 || l + fen[q][2] > 25 || p + fen[q][3] > 21) continue;
plus(f[j + fen[q][0]][k + fen[q][1]][l + fen[q][2]][p + fen[q][3]], g[j][k][l][p]);
}
}
}
}
}
fo(q, 1, 9) plus(f[fen[q][0]][fen[q][1]][fen[q][2]][fen[q][3]], 1);
if (nonono == 0) {
fo(q, 1, val - 1)
plus(f[las_[0] + fen[q][0]][las_[1] + fen[q][1]][las_[2] + fen[q][2]][las_[3] + fen[q][3]], 1);
}
fo(j, 0, 3) las_[j] += fen[val][j];
}
if (nonono == 0) f[las_[0]][las_[1]][las_[2]][las_[3]]++;
/*
fo(j, 0, 59) fo(k, 0, 37) fo(l, 0, 25) fo(p, 0, 21) {
if (! f[j][k][l][p]) continue;
printf("%d %d %d %d, %lld\n", j, k, l, p, cf0[0][j] * cf0[1][k] * cf0[2][l] * cf0[3][p]);
printf("%d\n", f[j][k][l][p]);
}
return 0;
*/
fd(j, 59, 0) fd(k, 37, 0) fd(l, 25, 0) fd(p, 21, 0)
plus(f[j][k][l][p], f[j + 1][k][l][p]);
fd(j, 59, 0) fd(k, 37, 0) fd(l, 25, 0) fd(p, 21, 0)
plus(f[j][k][l][p], f[j][k + 1][l][p]);
fd(j, 59, 0) fd(k, 37, 0) fd(l, 25, 0) fd(p, 21, 0)
plus(f[j][k][l][p], f[j][k][l + 1][p]);
fd(j, 59, 0) fd(k, 37, 0) fd(l, 25, 0) fd(p, 21, 0)
plus(f[j][k][l][p], f[j][k][l][p + 1]);
fo(j, 0, 59) fo(k, 0, 37) fo(l, 0, 25) fo(p, 0, 21)
g[j][k][l][p] = (ll)f[j][k][l][p] * f[j][k][l][p] % mo;
fo(j, 0, 59) fo(k, 0, 37) fo(l, 0, 25) fo(p, 0, 21)
nplus(g[j][k][l][p], g[j + 1][k][l][p]);
fo(j, 0, 59) fo(k, 0, 37) fo(l, 0, 25) fo(p, 0, 21)
nplus(g[j][k][l][p], g[j][k + 1][l][p]);
fo(j, 0, 59) fo(k, 0, 37) fo(l, 0, 25) fo(p, 0, 21)
nplus(g[j][k][l][p], g[j][k][l + 1][p]);
fo(j, 0, 59) fo(k, 0, 37) fo(l, 0, 25) fo(p, 0, 21)
nplus(g[j][k][l][p], g[j][k][l][p + 1]);
fo(j, 0, 59) {
if (cf0[0][j] > K) break;
fo(k, 0, 37) {
if (cf0[0][j] * cf0[1][k] > K) break;
fo(l, 0, 25) {
if (cf0[0][j] * cf0[1][k] * cf0[2][l] > K) break;
fo(p, 0, 21) {
if (cf0[0][j] * cf0[1][k] * cf0[2][l] * cf0[3][p] > K) break;
plus(ans, g[j][k][l][p]);
}
}
}
}
printf("%d\n", ans);
return 0;
}