做了一场cf 964 div4,本场链接放到这里了CFround964 div4 这场题质量真的很好
-好在也算ak了
A,B,C都没什么太多好说的,简单模拟即可,下面分享一下我的代码——
目录

A题
思路分析
简单两位数数位求和
代码实现
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define int long long
#define x first
#define y second
using namespace std;
void solve()
{
int n;
cin>>n;
cout<<n%10+n/10<<endl;
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
int t ;
cin >> t;
while(t--) solve();
}
B题
思路分析
直接模拟 Suneet 赢下局数的可能,很暴力-----
代码实现
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define int long long
#define x first
#define y second
using namespace std;
void solve()
{
int res = 0;
int c,d,a,b;
cin >> c >> d >> a >> b;
if((d>a&&c>=b)||(d>=a&&c>b)) res++;
if((d>b&&c>=a)||(d>=b&&c>a)) res++;
if((c>a&&d>=b)||(c>=a&&d>b)) res++;
if((c>b&&d>=a)||(c>=b&&d>a)) res++;
cout<<res<<endl;
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
int t ;
cin >> t;
while(t--) solve();
}
C题
思路分析
题目看起来很吓人,但是还是直接模拟就行,不过得注意一些细节,不然容易WA---
代码实现
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define int long long
#define x first
#define y second
using namespace std;
const int N = 2e5 + 10;
typedef pair<int,int> PII;
PII a[N];
void solve()
{
int flag = 0;
int n,s,m;
cin>>n>>s>>m;
for(int i = 1; i <= n; i++) cin>>a[i].x>>a[i].y;
sort(a+1,a+n+1);
if(a[1].x >= s || m - a[n].y >= s )
{
cout<<"YES"<<endl;
return ;
}
for(int i = 1; i < n; i++)
{
if(a[i+1].x - a[i].y >= s)
{
flag = 1;
cout<<"YES"<<endl;
break;
}
}
if(!flag) cout<<"NO"<<endl;
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
int t ;
cin >> t;
while(t--) solve();
}
D题
思路分析
算是思维题加上双指针,但其实不需要双指针一个指针也可以做,代码如下:
代码实现
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define int long long
#define x first
#define y second
using namespace std;
void solve()
{
string s,t;
cin>>s>>t;
int i = 0;
for(auto c:t)
{
while(i<s.size()&&s[i]!=c&&s[i]!='?')
{
i++;
}
if(i==s.size())
{
cout<<"NO"<<endl;
return ;
}
else
{
s[i] = c;
i++;
}
}
cout<<"YES"<<endl;
for(auto &c:s)
{
if(c=='?') c = 'a';
}
cout<<s<<endl;
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
int t ;
cin >> t;
while(t--) solve();
}
E题
思路分析
本题题意是在 l 到 r (包含l 和 r)这个区间内任意选两个数执行Op1和Op2,我们规定
- Op1:将x乘以3变为3x
- Op2:将y除以3向下取整变为[y / 3]
我们现在需要在l和r区间内任选两个数进行 两种不同的操作使整个序列的数都变为0,问最小操作次数。
- 因此我们可以想到贪心,当Op1只给0用,Op2给其他数用时会得到最小次数。所以我们应该先将最小的数l当成y一直进行Op2操作将其变为0,其他数当成x一直进行Op1操作。此时操作次数记为C[l]。
- 首先将第一步中进行Op1的数降回来,此时和第一步的次数一样为C[l],然后将l当成x执行Op1(反正一直为0),除l位置以外所有数当成y执行Op2,此时总次数为
- 将两步的次数相加之后总次数是
其实不难看出也就是
求和我们知道 l 和 r 在1到 的范围内,所以我们求和时要用到前缀和了,先把1到2e5+10之间的所有数除以3降到0所需要的步数存在step[N],先预处理前缀和,不然后面读入t 双重循环会TLE。
知道了这些 ,我们可以上代码了!——
代码实现
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define int long long
#define x first
#define y second
using namespace std;
const int N = 2e5 + 10;
const int N1 = 6e5 + 10;
int step[N];
int sum[N];
int get(int x)
{
int cnt = 0;
while(x)
{
cnt++;
x/=3;
}
return cnt;
}
void solve()
{
int l,r; cin>>l>>r;
int res = get(l);//左边界,推出来的公式
cout << sum[r] - sum[l-1] + res <<endl;
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
//必须先预处理,不然超时
int j = 0;
for(int i = 1; i <= N; i++)
{
step[++j] = get(i);
}//每个整数除以3降到0的步数
for(int i= 1;i <= N;i++) sum[i]=step[i]+sum[i-1];//前缀和
int t ;
cin >> t;
while(t--) solve();
}
F题
思路分析
本题其实说的是在一个长度为n只包含0,1的数组里选取k个数,
将取这个数组中长度为 k ( k为奇数)的所有子序列 ,并找出它们的中位数。
所有这些值的和是多少? 在0,1数组里取子序列算中位数,中位数无非只有0和1两种,求和时0对答案是没贡献的,所以我们只用算子序列中中位数为1的情况个数就行了。
首先我们知道在长度为k的序列中至少也要有ceil(k*1.0/2)个1才能保证中位数不为0,我们记为sum_1。
其次这样就不得不用到组合数模版了,我们在sum1(数组中1的个数)中取i个1,sum2(数组中2的个数)中取(k - i)个0,两个组合数相乘即为所有的情况种数,但是要注意范围问题,我们for循环从sum_1遍历,i必须小于等于sum1且小于k,还有一个就是(k-i)小于等于sum0才是合法范围
组合数模版在 求组合数C(a,b) 说太多了,下面上代码哈哈-------
代码实现
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define int long long
#define x first
#define y second
using namespace std;
const int mod = 1e9 + 7;
const int N = 2e5 + 10;
int fact[N],infact[N];
int qmi(int a,int k,int p)
{
int res = 1 % p;
while(k)
{
if(k & 1) res = (int)res * a % p;
a = (int)a * a % p;
k >>= 1;
}
return res;
}
void init()
{
fact[0] = infact[0] = 1;
for(int i = 1; i < N; i++)
{
fact[i] = (int)fact[i-1] * i % mod ;
infact[i] = (int)infact[i-1] * qmi(i,mod - 2,mod) % mod;
}
}
int C(int a,int b)//计算组合数
{
return (int)fact[a] * infact[b] % mod * infact[a-b] % mod;
}
void solve()
{
int n,k;
cin>>n>>k;
int sum1 = 0;
int sum0 = 0;
for(int i = 0; i < n; i++)
{
int x;
cin>>x;
if(x == 0) sum0++; else sum1++;
}
int sum_1 = ceil(k*1.0/2);//至少要有[k/2]+1个1才能保证中位数不为0
if(sum_1 > sum1)
{
cout<<"0"<<endl;
return;
}
int ans = 0;
for(int i = sum_1; i <= sum1 && i <= k ; i++)
{
if(k-i <= sum0)
ans = (ans + C(sum1,i) * C(sum0,k-i) % mod) % mod;
}
cout<<ans<<endl;
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
init();
int t;
cin >> t;
while(t--) solve();
return 0;
}
G1题
思路分析
交互题,G1可以查询10次,2的10次方为1024,正好大于1000没多少,x在2到999刻度出错,
那就直接二分,得注意交互题的格式
代码实现
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define int long long
#define x first
#define y second
using namespace std;
void solve()
{
int l = 1,r = 999,ans = -1;
while(l<=r)
{
int mid = l + r >> 1;
cout<< "?" << ' ' << mid << ' ' << mid << endl;
cout<<endl;
int s ; cin >> s;
if(mid * mid != s) r = mid - 1;
else l = mid + 1,ans = mid ;
}
cout<< "!" << " " << ans + 1 << endl;
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
int t ;
cin >> t;
while(t--) solve();
}
G2题
思路分析
交互题,G2只能查询7次,就不能二分了,那我们就三分区间,两个断点分别为m1,m2。
代码实现
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define int long long
#define x first
#define y second
using namespace std;
int query(int a,int b)
{
cout<<"?"<<" "<<a<<" "<<b<<endl;
int s1;
cin >> s1;
return s1;
}
void f(int a)
{
cout<<"!"<<" "<<a<<endl;
}
void solve()
{
//三分区间
int l = 1,r = 1000;
while(l + 2 < r)//注意边界
{
int m1 = l + (r - l) / 3;
int m2 = l + (r - l) / 3 * 2;
int s = query(m1,m2);
if(s == m1 *m2) l = m2; //m2左边未出错
else if(s == m1 * (m2 + 1)) //m1和m2中间出错
{
l = m1;
r = m2;
}
else r = m1;//否则为m1左边出错
}
if(l+1==r) f(r);//如果此时r就在l右边1格,则直接输出
else
{
int s = query(l,l+1);//否则再查询一下
if(s==l*(l+1)) f(l+2);
else f(l+1);
}
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
int t ;
cin >> t;
while(t--) solve();
}
好了,本篇cf题解分享到此结束,欢迎大家讨论交流!!之后我还会不定期分享,感谢大家观看,希望大家能点赞收藏加关注哦~~~~~