题意:给定一个数组,求使这个数组中所有元素的和为偶数的次数;
可以对数组中元素x进行操作,使x=x/2;
预处理求出1到N偶数变基数需要的操作次数,奇数变偶数的操作次数;
若sum为奇数,就找到使数字改变奇偶的最小次数就行
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
int n, t;
string a, b;
vector<int>dp(N),ou(N);
void slove()
{
cin >> n;
vector<int>a(n);
int sum = 0; int ans = INT_MAX;
int res = 0;
for (int i = 0; i < n; i++)
{
cin >> a[i];
sum += a[i];
if (a[i] % 2)
ans = min(ans, dp[a[i]]);
else if (a[i] != 0)
ans = min(ans, ou[a[i]]);
}
if (sum % 2)
cout << ans << endl;
else
cout << res<<endl;
}
int main() {
cin >> t;
for (int i = 0; 2 * i + 1 < N; i++)
{
dp[2 * i + 1] = dp[i] + 1;
ou[2 * i] = ou[i] + 1;
}
while (t--)
slove();
}
排序后,使序号靠后的数字是前面数字的倍数
需要注意的是记录排序前,每个位置的原本的位置
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
#define ll long long
int n, t;
string a, b;
vector<int>dp(N),ou(N);
void slove()
{
cin >> n;
vector<ll>a(n);
for (int i = 0; i < n; i++)
{
cin >> a[i];
}
vector<int>ind(n);
if (n == 1) { cout << 0 << '\n'; return; }
iota(ind.begin(), ind.end(), 1);
sort(ind.begin(), ind.end(), [&](int i, int j)
{
return a[i-1] < a[j-1];
});
sort(a.begin(), a.end());
int p = 0;
int j = 1;
int st = a[0];
vector<vector<int>>ans;
while (j<n)
{
while (j<n&&st == a[j])
j++;
if (j == n)break;
if (a[j] % st==0) { st = a[j]; j++; }
else {
int d= (a[j] / st + 1) * st-a[j];
ans.push_back({ind[j],d});
a[j] += d;
st = a[j];
j++;
p++;
}
}
cout << p << endl;
for (auto& t : ans)
cout << t[0] << " " << t[1] << endl;
}
int main() {
cin >> t;
while (t--)
slove();
}
题意比较绕,拓展比较好理解,就不说了,
对于给定字符串第i位来说,要求,拓展后,总共2*i-1个字符中,至少有i个字符与第i位相同。
有点像众数的概念。
这题是动态规划
转移方程和解释放在代码里面
#include <bits/stdc++.h>
using namespace std;
long long ans = 1;
int n; string a;
const int mod = 998244353;
void solve()
{
ans =1;
cin >> n;
cin >> a;
long long cnt = 1;
for (int i = 1; i < n; i++)
{
if (a[i] == a[i - 1])cnt = 2 * cnt % mod;/*如果与前一位相同,i之前,拓展后有i-1个a[i-1]的方法有cnt种,那么在a[i]和a[i-1]间无论放0还是1,都可以满足要求。*/
else cnt = 1;/*如果不同,那么在在i之前,拓展后至少有i-1个个a[i-1]那么此时,在a[i]和a[i-1]间不填入数字的话,至少有i-1个a[i-1],i-1个a[i](原本应该有2*i-1个,有一个没插入呢)那么此时a[i]和a[i-1]直接只能插入a[i]相同的值,所以cnt=1;*/
ans += cnt;
ans%=mod;
}
cout << ans << endl;
}
int main()
{
int t;
cin >> t;
while (t--)
solve();
return 0;
}
给一个数字n,然后有一个长度为n的隐藏的数组,由0到n-1构成;
找出其中的0;
可以输出? pos1 pos2
然后接受一个pos1 和pos2 的最大公因数
注意0与x的最大公因数为x
方法:
由于最大公因数小于等于这两个数的本身,那么对于任意数字与一个数字的最大公因数一定小于0与这个数字的最大公因数
也就是找查询最大值的下标(代码里面很直观);
#include <bits/stdc++.h>
using namespace std;
long long ans = 1;
int n; string a;
const int mod = 998244353;
void solve()
{
cin >> n;
int x = 1, y = 2;
int g1, g2,ans;
for (int i = 3; i <= n; i++)
{
cout << "? " << x << " " << i << endl;
cin >> g1;
cout << "? " << y << " " << i << endl;
cin >> g2;
if (g2 > g1)x = i;
if (g1 > g2)y = i;
}
cout << "! " << x << " " << y << endl;
cin >> ans;
}
int main()
{
int t;
cin >> t;
while (t--)
solve();
return 0;
}