比赛链接:

https://codeforces.com/contest/1647

D. Madoka and the Best School in Russia

题目大意:

一个数如果是 \(d\) 的倍数,那么它就是 \(good\) 的。
一个数是 \(good\) 的同时它又不能是两个 \(good\) 数的乘积,那么它就是 \(beautiful\) 的。
给一个 \(good\)\(x\) 以及 \(d\),判断有没有多于两种方案的 \(beautiful\) 数的组合方案,能让 \(x\) 变成一个或多个 \(beautiful\) 数的乘积。

思路:

首先清楚 \(beautiful\) 数是 \(d\) 的倍数,但是又不是 \(d * d\) 的倍数。
两种做法。
\(dp\) 做法

定义 \(dp_{i, j}\) 表示除以 \(j\) 之后当前数为 \(i\) 的方案数。
先所有的 \(j\),即列举 \(x\) 的每一个 \(good\) 因数,将它们记录下来。\(dp_{x, 1}\) 就是初始的状态,该方案数等于 1。找到一个最大的因数 \(k\)\(dp_{x / k, k} = dp_{x / k, k} + dp_{x, 1}\)。最后我们只要将所有让 \(x\) 变成 1 的方案总和求出来就可以了。

分类讨论的做法

首先将 \(x\) 分解成 \(d^k * b\),显然,若 \(k\) <= 1 的时候,找不到两种方案。
\(b\) 为合数的时候,肯定可以找到两种及以上的方案,即将 \(b\) 分解掉,然后分配给两个 \(d\),上面已经把小于两个 \(d\) 的情况考虑了。
\(b\) 为质数的时候,\(b\) 无法分解了,想要找到新的方案就要分解 \(d\),即 \(d\) 要是一个合数。
接下来考虑 \(k\) 的数量。
\(k\) == 2 的时候,找不到,不能分解 \(d\)
\(k\) == 3 的时候,\(d\) 不能是 \(b * b\),不然划分不了。
\(k\) >= 4 的时候,肯定可以找到两种方案。

代码:

dp

#include <bits/stdc++.h>
using namespace std;
#define pii pair <int, int>
#define fi first
#define se second
#define pb push_back
int T, x, d;
void solve(){
	cin >> x >> d;
	map < pii, int> dp;
	vector <int> v;
	dp[{x, 1}] = 1;
	for (int i = 1; i * i <= x; ++ i)
		if (x % i == 0){
			if (i % d == 0 && i % (d * d) != 0) v.pb(i);
			if (x != i * i && (x / i) % d == 0 && (x / i) % (d * d) != 0) v.pb(x / i);
		}
	int ans = 0;
	while (dp.size()){
		auto t = *dp.rbegin();
		if (t.fi.fi == 1) ans += t.se;
		for (auto i : v)
			if (t.fi.fi % i == 0 && i >= t.fi.se)
				dp[{t.fi.fi / i, i}] += t.se;
		dp.erase(t.fi);
	}
	if (ans >= 2) cout << "YES\n";
	else cout << "NO\n";
}
int main(){
	cin >> T;
	while (T--)
		solve();
	return 0;
}

分类

#include <bits/stdc++.h>
using namespace std;
int T, x, d;
bool judge(int x){
	for (int i = 2; i * i <= x; ++ i)
		if (x % i == 0)
			return false;
	return true;
}
void solve(){
    cin >> x >> d;
	int k = 0, b = x;
	while (b % d == 0){
		b /= d;
		k++;
	}
	cout << k << " " << b << "\n";
	if (k <= 1) cout << "NO\n";
	else {
		if (!judge(b)) cout << "YES\n";
		else{
			if (judge(d)) cout << "NO\n";
			else{
				if (k == 2) cout << "NO\n";
				else if (k >= 4) cout << "YES\n";
				else{
					if (d == b * b) cout << "NO\n";
					else cout << "YES\n";
				}
			}
		}
	}
}
int main(){
	cin >> T;
	while (T--)
		solve();
	return 0;
}
posted on 2022-03-14 21:04  Hamine  阅读(75)  评论(0编辑  收藏  举报