A.造数
倒着贪心,小于等于2时方案加1后输出,反之如果是奇数得先-1,再除2,偶数就直接除2
#include<bits/stdc++.h>
#define endl '\n'
#define mk make_pair
#define int long long
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 3e5+10;
const int mod = 998244353;
int n,m,k;
void sovle(){
int num=0;
cin>>n;if(n==0) {
cout<<0<<endl;
return;
}
while(n){
if(n<=2){
cout<<num+1<<endl;
return;
}else if(n%2){
n--;
}else{
n/=2;
}
num++;
}
}
signed main()
{
ios::sync_with_stdio(false), cin.tie(0),cout.tie(0);
int t = 1;
//cin>>t;
while (t--){
sovle();
}
return 0;
}
B.爱探险的朵拉
有点难,补不补待定吧,没找到合适的题解
C.有大家喜欢的零食吗
二分图最大匹配的板子题,之前没学过...匈牙利算法秒了
#include<bits/stdc++.h>
#define endl '\n'
#define mk make_pair
#define int long long
using namespace std;
typedef pair<int, int> PII;
const int N = 1e6+10;
int n,m,k;
bool vis[505];
int match[505];
vector<int>a[505];
bool dfs(int u){
for(int ed:a[u]){
if(vis[ed]) continue;
vis[ed]=1;
if(!match[ed]||dfs(match[ed])){
match[ed]=u;
return 1;
}
}
return 0;
}
void sovle(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>m;
for(int j=1;j<=m;j++){
cin>>k;
a[i].push_back(k);
}
}
int ans=0;
for(int i=1;i<=n;i++){
memset(vis,0,sizeof(vis));
if(dfs(i)) ans++;
}if(ans==n) cout<<"Yes"<<endl;
else cout<<"No"<<endl<<n-ans<<endl;
}
signed main()
{
ios::sync_with_stdio(false), cin.tie(0),cout.tie(0);
int t = 1;
//cin>>t;
while (t--){
sovle();
}
return 0;
}
D.小蓝的二进制询问
按位拆分后发现,每个位上是有循环节的,具体是从当前位的值-1开始循环的,循环的周期为2的当前位次(1是第1位,2是第2位,4是第3位......)次方,每个周期拥有的1的个数就是周期大小的一半。然后具体要算l到r区间的值,我们可以用前缀和S[r]-S[l-1]。
#include<bits/stdc++.h>
#define endl '\n'
#define mk make_pair
#define int long long
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 1e5+10;
const int mod = 998244353;
int n,m,k;
int check(int xx){
int num=0,vl=1,qu=2,bei=1;
while(vl<=xx){
int x=xx-vl+1;
num+=x/qu*bei;num%=mod;
num+=min(qu/2,x%qu);num%=mod;
vl*=2;qu*=2;bei*=2;
}return num;
}
void sovle(){
int x,y;
cin>>x>>y;
cout<<check(y)-check(x-1)<<endl;
}
signed main()
{
ios::sync_with_stdio(false), cin.tie(0),cout.tie(0);
int t = 1;
cin>>t;
while (t--){
sovle();
}
return 0;
}
F.两难抉择新编
将所有能选的数的总和算出来发现,最坏的情况下也不超过1e7,所以这题暴力枚举就可以过
一个数异或它本身等于0,任何数异或0都等于它本身
#include<bits/stdc++.h>
#define endl '\n'
#define mk make_pair
#define int long long
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 2e5+10;
const int mod = 998244353;
int n,m,k;
int a[N];
void sovle(){
cin>>n;
int num=0;
for(int i=1;i<=n;i++){
cin>>a[i]; num^=a[i];
}
int max1=-1;
for(int i=1;i<=n;i++){
int sum=num^a[i];
for(int j=1;j<=n/i;j++){
max1=max(sum^(a[i]+j),max1);
max1=max(sum^(a[i]*j),max1);
}
}
cout<<max1<<endl;
}
signed main()
{
ios::sync_with_stdio(false), cin.tie(0),cout.tie(0);
int t = 1;
//cin>>t;
while (t--){
sovle();
}
return 0;
}
G.旅途的终点
如果在第x个国家,即使采取最优策略也无法畅游,那么后面的国家也是无法畅游的,说明在某个位置开始答案就变得不可取,显然答案具有单调性,所以我们二分畅游的国家个数。对于二分出的个数,我们在这些国家中选最大的k个使用神力,如果这样还不能全部畅游选中的国家,那么就是取大了,反之就是取小了。
#include<bits/stdc++.h>
#define endl '\n'
#define mk make_pair
#define int long long
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 2e5+10;
const int mod = 998244353;
int n,m,k;
int a[N];
bool ok(int x){
vector<int>q(x);
for(int i=0;i<x;i++){
q[i]=a[i];
}sort(q.begin(),q.end());
int f=m;
for(int i=1;i<=x-k;i++){
f-=q[i];
if(f<=0) return 0;
}
return 1;
}
void sovle(){
cin>>n>>m>>k;
for(int i=0;i<n;i++) cin>>a[i];
int l=0,r=n,ans=0;
while(l<=r){
int mid=(l+r)>>1;
if(ok(mid)){
ans=mid;
l=mid+1;
}else r=mid-1;
}if(ans>n) ans=n;
cout<<ans<<endl;
}
signed main()
{
ios::sync_with_stdio(false), cin.tie(0),cout.tie(0);
int t = 1;
//cin>>t;
while (t--){
sovle();
}
return 0;
}
H.两难抉择
操作一情况唯一,操作二最优在最大的数✖️n
#include<bits/stdc++.h>
#define endl '\n'
#define mk make_pair
#define int long long
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 3e5+10;
const int mod = 998244353;
int n,m,k;
void sovle(){
cin>>n;
int sum=n,num=0,max1=0;
vector<int>a(n),b(n);
for(int i=0;i<n;i++){
cin>>a[i];
sum+=a[i];
b[i]=a[i];
num+=b[i];
max1=max(max1,b[i]);
}num-=max1;num+=n*max1;
cout<<max(num,sum)<<endl;
}
signed main()
{
ios::sync_with_stdio(false), cin.tie(0),cout.tie(0);
int t = 1;
//cin>>t;
while (t--){
sovle();
}
return 0;
}
I.除法移位
式子可以化成a1➗(a2✖️a3✖️a4···),要使值最大,则要使值最大,则让a1取可取范围内的最大值,可取范围就是max(0,n-m+1)到n,特别的如果a1就是最大值,则不用操作
#include<bits/stdc++.h>
#define endl '\n'
#define mk make_pair
#define int long long
using namespace std;
typedef pair<int, int> PII;
const int N = 1e6+10;
int n,m,k;
void sovle(){
cin>>n>>m;
vector<int>a(n);
int max1=0,u=0;
for(int i=0;i<n;i++){
cin>>a[i];
}
for(int i=n-1;i>=max((long long)0,n-m);i--){
if(a[i]>max1){
max1=a[i];
u=n-i;
if(u==n) u=0;
}
}
cout<<u<<endl;
}
signed main()
{
ios::sync_with_stdio(false), cin.tie(0),cout.tie(0);
int t = 1;
//cin>>t;
while (t--){
sovle();
}
return 0;
}
K.图上计数(Easy)
蒽,红温题,甚至用上了并查集,后来发现读假了。
可以把边全部删除,再任意地合成,那么只要n不等于1,我们总是可以合成n/2和(n/2+n%2)使得乘积最大
#include<bits/stdc++.h>
#define endl '\n'
#define mk make_pair
#define int long long
using namespace std;
typedef pair<int, int> PII;
const int N = 1e6+10;
int n,m,k;
void sovle(){
cin>>n>>m;
cout<<n/2*(n/2+n%2);
}
signed main()
{
ios::sync_with_stdio(false), cin.tie(0),cout.tie(0);
int t = 1;
//cin>>t;
while (t--){
sovle();
}
return 0;
}