GMOJ 6831 lover

GMOJ 6831 lover

数位DP+高维前缀和

我们设\(h_{s, a, b, c, d}\)为乘积为\(2^a\times3^b\times5^c\times7^d\),其中\(s\)的第i位为0 / 1表示= / >这一维指定的指数。

\[ans=\sum h_{S,a,b,c,d} \cdot h_{T,a,b,c,d} \quad (T\subseteq \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;
}

posted @ 2020-10-24 21:58  鼠曲雪兔子  阅读(111)  评论(0编辑  收藏  举报