比赛链接:
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;
}