A.篮球比赛
链接: A
心理路程:第一时间是推规律,30s过后感觉是斐波那契,但是不是很相信自己,就由往下推一个数,得出规律, 原来是与奇偶性相关;`
#include <iostream>
using namespace std;
int main(){
int t ;cin>>t;
while(t--){
int n;
cin>>n;
if(n==1) cout<<0<<endl;
else if(n%2==0){
cout<<n-1<<endl;
} else cout<<n<<endl;
}
return 0;
}
B.string
链接: B
心理路程:看到英文题不是很想读,但是没办法,总要跳出舒适圈,读完立马感觉是string字典对比,但不是很自信,把样例全都粘贴补上,全部对上才敢交
#include <iostream>
#include <cstring>
using namespace std;
void slove(){
string a,b;
cin>>a>>b;
if(a==b) cout<<a<<'='<<b<<endl;
else if(a<b) cout<<a<<'<'<<b<<endl;
else cout<<a<<'>'<<b<<endl;
}
int main(){
slove();
return 0;
}
c.二分
链接: 二分板子link
链接: C题目
心理路程:跟着榜打,但是一直没出,当时很焦急,感觉不应该这样啊,然后感觉板子写错了,de很长时间,但是一直没找出来;
收获:忘是固然,多看多练多写就行,要精确板子;
#include <iostream>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
typedef long long ll;
const ll p=1e9+7;
ll a,b,x;
ll getN(ll t){
ll cc=0;
while(t){
cc++;
t/=10;
} return cc;
}
void slove(){
cin>>a>>b>>x;
ll l=0,r=1e9;
//没有l=1;
while(l<r){
ll mid=(l+r+1)>>1;
if(a*mid+b*getN(mid)<=x){
l=mid;
} else r=mid-1;
} cout<<l<<endl;
}
int main(){
slove();
return 0;
}
做的时候重看下范围,x是1e18,于是就让r=1e18,l=1了,这个l取错了
该l=0,然后又wa,仔细读题,商店最多卖出1e9个,所以要写为 r=1e9
读题细心很重要
D.打篮球
链接: D
心理路程:第一眼,飘过,没看到连续观看,因为焦急,敲完直接交了,wa。然后再看题,想是前缀和,是没错,但是我的想法是4个单层for循环解决,很显然第一个样例跑出来就超时了;
赛后思考:很明显,是把问题想复杂了,前缀和只加上下标为0的即可。
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N=2e5+9;
ll sum[N],a[N];
void slove(){
ll n,m;cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i];
}
ll x;
ll ans=0;
for(int i=1;i<=n;i++){
cin>>x;
if(x) ans+=a[i],sum[i]=sum[i-1];
else sum[i]=sum[i-1]+a[i];
}
ll ss=0;
//cout<<ans<<endl;
for(int i=m;i<=n;i++){
ss=max(ss,sum[i]-sum[i-m]);
//cout<<ss<<endl;
} cout<<ss+ans<<endl;
}
int main(){
slove();
return 0;
}
E.鸡哥雕像
链接: E
心理路程:第一次写的时候感觉是前缀乘,于是就写了下来,但是果不其然,wa,然后再在乘的地方全部取mod,但是样例没过,于是又思考,前缀和的时候大于mod的取mod,细想,存在漏洞,之后不知道怎么解决,很焦急
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const ll N=2e5,p=998244353;
ll sum[N],a[N],ss[N];
void slove(){
ll n; cin>>n;
sum[0]=1;
for(int i=1;i<=n;i++){
cin>>a[i];
sum[i]=sum[i-1]*a[i];
if(sum[i]>p) sum[i]%=p;
}
reverse(a+1,a+n+1);
ss[0]=1;
for(int i=1;i<=n;i++){
// cout<<a[i]<<endl;
ss[i]=ss[i-1]*a[i];
if(ss[i]>p) ss[i]%=p;
}
for(int i=1;i<=n;i++){
cout<<(sum[i-1]*ss[n-i])%p<<' ';
}
}
int main(){
slove();
return 0;
}
F.除二排序
链接: F
心理路程:这题好像没时间看,晃晃而过
赛后补题:思考过优先队列,不是很行,在思考存入set,也存在矛盾,
关键在于这个数是否有,想到了标记;
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
void slove(){
ll n,x; cin>>n;
vector<bool>bj(n+1,0),aa(n+1,1);
bj[0]=1;
for(int i=1;i<=n;i++){
cin>>x;
if(x<=n&&!bj[x]) bj[x]=1;
else {
while(x){
x/=2;
if(x!=0&&x<=n&&!bj[x]) {
bj[x]=1;
break;
}
}
}
}
if(bj==aa) puts("YES");
else puts("NO");
}
int main(){
ll t; cin>>t;
while(t--)
slove();
return 0;
}
G.01字符
链接: G
心理路程: 第一眼,这题好熟悉,是不是最近写的一题?细看不是,硬是看了半天没敢写;
赛后补题:这题我不是很会,学习了一些大佬的前缀和思想,才a,这里的对应关系其实很好,把0看成-1,前缀和为0的则满足区间要求,求长即可
错误代码:tle,很显然暴力是不行的
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
ll sum[100500];
void slove(){
ll n; cin>>n;
string s; cin>>s;
for(int i=0;i<n;i++){
if(s[i]=='0') sum[i+1]=sum[i]-1;
else sum[i+1]=sum[i]+1;
}
ll ans=0;
for(ll i=1;i<=n;i++){
for(ll j=i;j<=n;j++){
if(sum[j]-sum[i-1]==0){
ans=max(ans,j-i+1);
}
}
} cout<<ans<<endl;
}
int main(){
//ll t; cin>>t;
slove();
return 0;
}
思考片刻,加个map做下标,前缀和为0的时候就标记下,一个for就以了
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
using namespace std;
typedef long long ll;
ll n;
//const int N=2e5+9;
//const ll p=998244353;
void slove(){
ll n;cin>>n;
ll ans=0,sum=0;
vector<char>s(n+1);
map<ll,ll>mp;
for(ll i=1;i<=n;i++){
cin>>s[i];
if(s[i]=='0'){
sum+=-1;
}else sum+=1;
if(sum!=0&&!mp[sum]) mp[sum]=i;
else {
ans=max(ans,i-mp[sum]);
//cout<<i-mp[sum]<<endl;
}
} cout<<ans<<endl;
}
int main(){
slove();
return 0;
}
H.正负数
链接: H
赛后补题:把问题简单话就行了,找到特征关系,正负性,全局关系,找到符合要求的负数区间,正数区间就可以出来了
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
using namespace std;
typedef long long ll;
ll n;
void slove(){
ll n,x; cin>>n;
map<ll,ll>mp;
ll tt=1,ans=0;
mp[-1]=1;//本身也是
for(int i=1;i<=n;i++){
cin>>x;
if(x<0) tt*=-1;
ans+=mp[tt];//巧妙的解决了配对区间
mp[tt*-1]++;//为下次相加铺垫
} cout<<ans<<' '<<(n*(n+1))/2-ans;
}
int main(){
slove();
return 0;
}
I.小dp
链接: I
赛后补题:说实话,本来就很恐惧dp的,自身对其的掌握不是很好,但是要走出舒适圈,就要不断向前。本身,我自己思考后发现了倍数关系,感觉不用dp,从暴力,前缀和,到出现【1,5】时,而基数是5该怎么办?参考了大佬们的dp思路,一个做长度,一个做基数;最后勉强a出
#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
using namespace std;
typedef long long ll;
const ll N=1e9+7;
ll dp[2500][2500];
void slove(){
ll n,m; cin>>n>>m;
for(ll i=1;i<=n;i++) dp[1][i]=1;//初始话
for(ll i=2;i<=m;i++){ //长度
for(ll j=1;j<=n;j++) //基数
for(ll k=1;k*j<=n;k++) //倍数
dp[i][j]=(dp[i][j]+dp[i-1][j*k])%N;
}
ll ans=0;
for(int i=1;i<=n;i++){
ans+=dp[m][i];
if(ans>=N) ans%=N;
} cout<<ans;
}
int main(){
slove();
return 0;
}
可能真的很菜吧,补题的同时又过了一遍,感觉有些还没有吃透,come on!