GMOJ 6831 lover
数位DP+高维前缀和
我们设(h_{s, a, b, c, d})为乘积为(2^a imes3^b imes5^c imes7^d),其中(s)的第i位为0 / 1表示= / >这一维指定的指数。
[ans=sum h_{S,a,b,c,d} cdot h_{T,a,b,c,d} quad (Tsubseteq complement_US)
]
就是说当你(S_i)为1时,(T_i)一定为0,当(S_i)为0时,(T_i)可以为0/1。
#include <cstdio>
#define inc(x, y) (x=(x+(y))%mods)
#define sqr(x) ((x)*(x)%mods)
#define min(x, y) ((x)<(y) ? (x) : (y))
using namespace std;
typedef long long ll;
const int maxl=18, mods=998244353, prim[4]={2, 3, 5, 7};
void toArray(ll x, int a[]) {
a[0] = 0;
for (; x>0; x/=10) a[++a[0]] = x%10;
}
void initPri(int n, int a[]) {
for (int i=0; i<4; i++) {
a[i] = 0;
for (int t=prim[i]; n%t==0; a[i]++, t*=prim[i]);
}
}
int main() {
freopen("lover.in", "r", stdin);
freopen("lover.out", "w", stdout);
static ll f[maxl+1][3*maxl+1][2*maxl+1][maxl+1][maxl+1][2], h[16][3*maxl+2][2*maxl+2][maxl+2][maxl+2];
static int t[maxl+1], pi[10][4];
ll n, k;
scanf("%lld %lld", &n, &k);
toArray(n, t);
for (int i=1; i<10; i++) initPri(i, pi[i]);
f[0][0][0][0][0][0] = f[0][0][0][0][0][1] = 1;
for (int i=1; i<=t[0]; i++) {
for (int j=1; j<10; j++) {
for (int a=pi[j][0]; a<=3*i; a++) {
for (int b=pi[j][1]; b<=2*i; b++) {
for (int c=pi[j][2]; c<=i; c++) {
for (int d=pi[j][3]; d<=i; d++) {
int o=a-pi[j][0],
p=b-pi[j][1],
q=c-pi[j][2],
r=d-pi[j][3];
inc(f[i][a][b][c][d][0],
f[i-1][o][p][q][r][0]);
if (j<t[i]) {
inc(f[i][a][b][c][d][1],
f[i-1][o][p][q][r][0]);
} else if (j==t[i]) {
inc(f[i][a][b][c][d][1],
f[i-1][o][p][q][r][1]);
}
}
}
}
}
}
}
for (int i=1; i<=t[0]; i++) {
for (int a=0; a<=3*i; a++) {
for (int b=0; b<=2*i; b++) {
for (int c=0; c<=i; c++) {
for (int d=0; d<=i; d++) {
inc(h[0][a][b][c][d], f[i][a][b][c][d][i==t[0]]);
}
}
}
}
}
for (int i=1; i<16; i++) {
int j[4], pos, nj[4], ni;
for (pos=0; ((i>>pos)&1)==0; pos++);
ni = i^(1<<pos);
for (j[0]=3*t[0]; j[0]>=0; j[0]--) {
for (j[1]=2*t[0]; j[1]>=0; j[1]--) {
for (j[2]=t[0]; j[2]>=0; j[2]--) {
for (j[3]=t[0]; j[3]>=0; j[3]--) {
for (int k=0; k<4; k++) nj[k]=j[k];
nj[pos]++;
h[i][j[0]][j[1]][j[2]][j[3]] =
(h[i][nj[0]][nj[1]][nj[2]][nj[3]] +
h[ni][nj[0]][nj[1]][nj[2]][nj[3]])%mods;
}
}
}
}
}
int a, b, c, d;
ll o, p, q, r, ans=0;
for (a=0, o=1; a<=3*t[0] && o<=k; a++, o*=2) {
for (b=0, p=1; b<=2*t[0] && o*p<=k; b++, p*=3) {
for (c=0, q=1; c<=t[0] && o*p*q<=k; c++, q*=5) {
for (d=0, r=1; d<=t[0] && o*p*q*r<=k; d++, r*=7) {
for (int i=0; i<16; i++) {
int t=15^i;
inc(ans, h[i][a][b][c][d]*h[t][a][b][c][d]%mods);
for (int j=(t-1)&t; j!=t; j=(j-1)&t) {
inc(ans, h[i][a][b][c][d]*h[j][a][b][c][d]%mods);
}
}
}
}
}
}
printf("%lld", ans);
fclose(stdin);
fclose(stdout);
return 0;
}