C. Pull Your Luck
思路:打表+推导
打表看出有循环,大概是2*n必定循环。自己推导一遍证明:
所以我们暴力 min(p,2n)即可
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define endl "\n"
#define int long long
const int N = 1e5 + 100;
void mysolve()
{
int n, x, p;
cin >> n >> x >> p;
int sum = 0;
for (int i = 1; i <= 2 * n && i <= p; ++i)
{
sum += i;
if (sum % n == (n - x) % n)
{
cout << "YES" << endl;
return;
}
}
cout << "NO" << endl;
}
int32_t main()
{
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
ll t;
cin >> t;
while (t--)
{
mysolve();
}
system("pause");
return 0;
}
D. Accommodation
思路:贪心
- 假设字符串有cnt个1,显然最多cnt户人
- 讨论最少
- 如果我们能让2个一起,就可以减少一户了,每凑成一对11,我就等价于成功消灭1户(最多凑m/4户,剩下就只能单了)
- 讨论最多:
- 我们需要尽可能让1能自成一家,换句话说,不想让11凑一起。11凑一起最多也就只能m/4对,如果我们这m/4对都尽可能挤满了不是11对的,是不是我的结果就会尽可能大。答案是cnt-min(two1,m/4)
- 所以,我们每次找不是11的对去匹配,配到m/4对(配不到,只能没办法剩下对数只能是11了,每算入一对11,我们就等于血亏一户)。所以答案是cnt-(m/4-min(m/4,two2))
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define endl "\n"
void mysolve()
{
int n, m;
cin >> n >> m;
string s;
int minn = 0, maxn = 0;
while (n--)
{
cin >> s;
int two = 0, cnt = count(s.begin(), s.end(), '1');//先用count记录字符串1的个数
for (int i = 0; i < m - 1; ++i)if (s[i] == '1' && s[i + 1] == '1')two++, i++;//第一个two记录11对数
two = min(m / 4, two);
minn += cnt - two;
two = 0;//这个two记录不是11的对数
for (int i = 0; i < m - 1; ++i)if (s[i] != '1' || s[i + 1] != '1')two++, i++;
two = min(m / 4, two);
maxn += cnt - (m / 4 - two);
}
cout << minn << ' ' << maxn << endl;
}
int32_t main()
{
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
mysolve();
system("pause");
return 0;
}