代码求优化
  • 板块题目总版
  • 楼主Adolfo_North
  • 当前回复0
  • 已保存回复0
  • 发布时间2024/8/4 12:40
  • 上次更新2024/8/4 14:36:31
查看原帖
代码求优化
616964
Adolfo_North楼主2024/8/4 12:40

题目:求有多少个长度为 n 且任意相邻两个数的最大公约数都不为 k 的排列?

#include <bits/stdc++.h>
using namespace std;
const int N = 3005, M = (1 << 10) + 1, mod = 998244353;
int n, k, m;
int f[N][M][11],cont[N];
int dfs(int t, int l, int g) {
	if (f[t][g][l] != -1) return f[t][g][l];
	if (t == 0) return f[t][g][l] = 1;
	if (!g) {
		int ans = 1;
		for(int i=2;i<=t;i++) ans = (1ll * ans * i) % mod;
		return f[t][g][l] = ans;
	}
	int res = 0;
	if (t - cont[g] > 0) res = (1ll * (t - cont[g]) * dfs(t - 1, 0, g)) % mod;
	if (g) {
		int x = g;
		while (x) {
			int y = log2(x & -x) + 1;
			if (l == 0 || __gcd(l, y) != 1)
				res = (res + dfs(t - 1, y, g ^ (x & -x))) % mod;
			x -= x & -x;
		}
	}
	return f[t][g][l] = res;
}
int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	freopen("permutation.in", "r", stdin);
	freopen("permutation.out", "w", stdout);
	cin >> n >> k;
	m = n / k;
	int l = (1 << m) - 1;
	for(int i=1;i<=l+1;i++) cont[i]=cont[i-(i&-i)]+1;
	memset(f, 0xff, sizeof f);
	cout << dfs(n, 0, l);
	return 0;
}
2024/8/4 12:40
加载中...