Codeforces Round 883 (Div. 3)
E2. Rudolf and Snowflakes (hard version)
题意:问一个数 是不是某个正整数 从 开始等比数列求和的结果。
题解:我们发现当 的时候,我们发现 ,因此我们可以对 的取值范围进行分类讨论。当 的时候,就直接预处理爆搜即可;当 的时候,我们只需判断 是否有解,即 是不是大于等于 的正整数。
具体代码如下:
#pragma GCC optimize(2)
#include <iostream>
#include <algorithm>
#include <array>
#include <bitset>
#include <chrono>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <vector>
#define int long long
#define pi acos(-1)
#define quick_cin() cin.tie(0),ios::sync_with_stdio(false)
#define endl "\n"
#define pb push_back
#define mkp make_pair
#define all(x) x.begin(), x.end()
#define ul (u << 1)
#define ur (u << 1 | 1)
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
const int N = 6000, M = 600, INF = 1e18;
const int mod = 998244353;
int T = 1;
int res = 0;
int ans = 0;
int n, m, k, q;
map<int, int> S;
void init()
{
for (__int128 i = 2; i <= 1e6; i ++ )
{
__int128 a = 1 + i + i * i, b = i * i * i;
while (a <= INF)
{
S[a] = 1;
a += b;
b *= i;
}
}
}
void solve()
{
cin >> n;
if (S[n]) cout << "YES\n";
else
{
int k = 4 * n - 3;
int _k = sqrt(k);
if (_k * _k == k && (_k - 1) % 2 == 0 && (_k - 1) / 2 >= 2)
cout << "YES\n";
else
cout << "NO\n";
}
}
signed main()
{
init();
quick_cin();
cin >> T;
while (T -- )
{
solve();
}
}
F. Rudolph and Mimic
题解:先至多操作两次输出“- 0”不改变原数组,此后一定会有某个类型的的数量加一,且有某个类型的数量减一。此时目标一定在数量加一的类型中,我们删去所有其他类型的物品。 然后再操作不超过一次,这个物品一定又会变成其他类型,这样就能找出来这个物品的位置了。
具体代码如下:
#pragma GCC optimize(2)
#include <iostream>
#include <algorithm>
#include <array>
#include <bitset>
#include <chrono>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <vector>
#define int long long
#define pi acos(-1)
#define quick_cin() cin.tie(0),ios::sync_with_stdio(false)
//#define endl "\n"
#define pb push_back
#define mkp make_pair
#define all(x) x.begin(), x.end()
#define ul (u << 1)
#define ur (u << 1 | 1)
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
const int N = 10, M = (1 << N), INF = 1e9;
const int mod = 998244353;
int T = 1;
int res = 0;
int ans = 0;
int n, m, k, q;
map<int, int> S;
void solve()
{
S.clear();
cin >> n;
vector<int> a(n);
for (int i = 0; i < n; i ++ ) cin >> a[i], S[a[i]] ++ ;
int t, flag = 0;
while (1)
{
cout << "- 0" << endl;
vector<int> b(n);
map<int, int> cnt;
for (int i = 0; i < n; i ++ )
{
cin >> b[i];
if (b[i] < 0 || b[i] > 9)
{
cout << "! " << i + 1 << endl;
return;
}
cnt[b[i]] ++ ;
}
for (auto [x, y] : cnt)
if (S[x] < y)
{
t = x, flag = 1;
break;
}
if (flag)
{
vector<int> c;
for (int i = 0; i < n; i ++ )
if (b[i] != t) c.pb(i + 1);
cout << "- " << c.size();
for (auto x : c) cout << " " << x;
cout << endl;
n -= c.size();
break;
}
}
while (1)
{
vector<int> b(n);
for (int i = 0; i < n; i ++ ) cin >> b[i];
for (int i = 0; i < n; i ++ )
if (b[i] != t)
{
cout << "! " << i + 1 << endl;
return;
}
cout << "- 0" << endl;
}
}
signed main()
{
quick_cin();
cin >> T;
while (T -- )
{
solve();
}
}
G. Rudolf and CodeVid-23
题意:有 种病 种药第 种药需要连续吃 次,会治一些病,但也有一些后遗症,治病的方式以两个 串给出,第一个串中为 的位表示该位下标表示的病可以被治好,然后第二个串中为 的位表示该位下标表示的病是这种药带来的。
然后给你一个初始的得病状态的 串, 表示得, 表示没得,然后问你这些药最少吃几次可以全部治好,不能全部治好就输出 。
题解:考虑建图,对于建边,对于一个状态,吃下一种药,会变成下一个状态,我们可以连一条从原状态向结果状态距离为 的边;于是我们发现如果我们可以治好,则初始状态与 是存在一条边的。
考虑两个状态的值,当状态为 时, 表示该药治病的序列, 表示后遗症的序列,那么结果状态就是 ;对于每种药都对所有可能情况建边,最后 跑一遍即可。
具体代码如下:
#pragma GCC optimize(2)
#include <iostream>
#include <algorithm>
#include <array>
#include <bitset>
#include <chrono>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <vector>
#define int long long
#define pi acos(-1)
#define quick_cin() cin.tie(0),ios::sync_with_stdio(false)
#define endl "\n"
#define pb push_back
#define mkp make_pair
#define all(x) x.begin(), x.end()
#define ul (u << 1)
#define ur (u << 1 | 1)
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
const int N = 10, M = (1 << N), INF = 1e9;
const int mod = 998244353;
int T = 1;
int res = 0;
int ans = 0;
int n, m, k, q;
string x;
int S;
void solve()
{
cin >> n >> m >> x;
bitset<N> cand(x);
S = cand.to_ulong();
vector<int> e[M], w[M];
while (m -- )
{
int c;
string u, v;
cin >> c >> u >> v;
bitset<N> U(u), V(v);
int a = U.to_ulong(), b = V.to_ulong();
for (int i = 0; i < (1 << n); i ++ )
{
int to = i & (~a) | b;
e[i].pb(to), w[i].pb(c);
}
}
vector<int> d(1 << n, INF);
vector<bool> st(1 << n);
priority_queue<PII, vector<PII>, greater<PII> > heap;
d[S] = 0;
heap.push({0, S});
while (heap.size())
{
auto [_, t] = heap.top();
heap.pop();
if (st[t]) continue;
st[t] = true;
for (int i = 0; i < e[t].size(); i ++ )
{
int j = e[t][i], dis = w[t][i];
if (d[j] > d[t] + dis)
{
d[j] = d[t] + dis;
heap.push({d[j], j});
}
}
}
if (d[0] > INF / 2) cout << "-1\n";
else cout << d[0] << endl;
}
signed main()
{
quick_cin();
cin >> T;
while (T -- )
{
solve();
}
}