A. 取特殊情况 1 n-3 1 1
#include <bits/stdc++.h>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
cout<<'1'<<' '<<n-3<<' '<<'1'<<' '<<'1'<<endl;
}
}
B. 记录出现次数最多的数出现了多少次 每次进行一次1操作 就判断进行几次二操作 要是没有打到目的数组 就再次循环找
#include <bits/stdc++.h>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--)
{
int xi=0;
int n,x;
cin>>n;
map<int,int>mp;
for(int i=0;i<n;i++)
{
cin>>x;
mp[x]++;
if(mp[x]>mp[xi])xi=x;
}
int sum=mp[xi];
int ans=0;
while(sum<n)
{
ans++;
if(sum*2>n)ans+=n-sum;
else ans+=sum;
sum*=2;
}
cout<<ans<<endl;
}
}
C. 二分 第一种感染就是感染他的兄弟(相同跟的) 第二种感染就是我们可以任意指定 所以我们就贪心的去想 我们肯定是先感染兄弟多的 让他一直可以进行1 操作 如果一共有cnt次操作 那么我么能感染的第一个最大就可以是进行了cnt-1次操作一 感染的第二个最大就是进行了cnt-2次操作二 我们只需再加上操作二的次数 即cnt的次数 进行二分答案即可
#include <bits/stdc++.h>
using namespace std;
//#define int long long
#define pb push_back
const int INF=0x3f3f3f3f;
const int N=1e6+10,M=1e6+10;
const int maxn=2e5+10;
vector<int> g[maxn];
int n,cnt,b[maxn];
bool check(int mid){
int maxx=0;
for(int i=1,j=mid-1;i<=cnt;i++,j--){
maxx+=max(0,b[i]-j);
}
return mid-cnt>=maxx;
}
void solve(){
int n;cin>>n;
for(int i=1;i<=n;i++)g[i].clear();
for(int i=2;i<=n;i++){
int x;cin>>x;
g[x].pb(i);
}
cnt=1;b[1]=0;
for(int i=1;i<=n;i++){
if(g[i].size()){
b[++cnt]=g[i].size()-1;
}
}
sort(b+1,b+1+cnt,greater<int>());
int l=cnt,r=n;
while(l<r){
int mid=l+r>>1;
if(check(mid))r=mid;
else l=mid+1;
}
cout<<r<<'\n';
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
int t;cin>>t;
//int t=1;
while(t--){
solve();
}
}
D. 交互题 题意是 我们找出x 通过询问 gcd(a+x,b+x) 因为不超过30次 我们可以想到位运算 (这玩意你咋二分) 位运算的话就是每次都确定x的一位 那么怎么判断这一位是1还是0呢 我们就可以用 000==2的3次方 但是100 不是2的3次方 如果我们想知道第i位是不是1 我们就可以更新他的后缀 让他变成1000 的形式 再用一个2的i次方加上他 看看他是不是进位 如果进位就是1 否则就是0 我们就可以每次记录ansi 表示i位的查询gcd(x−ansi+2i+1,x−ansi+2i+1+2i+2)=gcd(x−ansi+2i+1,2i+2) 来确定第 i+1 位的值
#include <bits/stdc++.h>
using namespace std;
//#define int long long
#define pb push_back
#define ll long long
const int INF=0x3f3f3f3f;
const int N=1e6+10,M=1e6+10;
const int maxn=2e5+10;
vector<int> g[maxn];
int n,cnt,b[maxn];
ll A[35];
void init(){
ll num=1;
for(int i=0;i<=30;i++){
A[i]=num,num*=2;
}
}
void solve(){
ll res,ans=0;
for(int i=0;i<30;i++){
ll a=A[i]-ans,b=A[i]+A[i+1]-ans;
cout << "? " << a << ' ' << b << endl;
cin>>res;
if(res==A[i+1])
ans^=(1ll<<i);
}
cout << "! " << ans << endl;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
init();
int t;cin>>t;
//int t=1;
while(t--){
solve();
}
}