目录
A.柠檬可乐
阅读理解题,依照题目直接模拟即可
void solve(){
int a,b,k; cin>>a>>b>>k;
if(a>=k*b) cout<<"good"<<endl;
else cout<<"bad"<<endl;
return ;
}
B.左右互博
简单博弈,我们要找到操作的本质是什么我们可以发现,n最后一定是变成n个1也就是说一定要进行n-1次操作,如果能理解到这里那就是判断奇偶了
void solve(){
cin>>n;
int ans=0;
for(int i=1;i<=n;i++){
int x; cin>>x;
ans+=(x-1)&1;
}
cout<<(ans&1 ? "gui" : "sweet")<<endl;
return ;
}
C.冬眠
简单模拟,可以发现明显的数据范围很小的这件事情我们计算一下直接模拟所需要的时间,发现是可以通过的所以直接暴力模拟即可
void solve(){
cin>>n>>m>>x>>y;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>s[i][j];
cin>>p>>q;
for(int i=1;i<=q;i++){
int op,x; cin>>op>>x;
a[i]={op,x};
}
while(p--){
for(int i=1;i<=q;i++){
auto [op,x]=a[i];
if(op==1){
char y=s[x][m];
for(int i=m;i>1;i--)
s[x][i]=s[x][i-1];
s[x][1]=y;
}
else{
char y=s[n][x];
for(int i=n;i>1;i--)
s[i][x]=s[i-1][x];
s[1][x]=y;
}
}
}
cout<<s[x][y]<<endl;
return ;
}
D.守恒
简单思维,我们可以发现又是典型的加一减一操作那么总和一定是不变的,由于操作次数不限制,那么这个数组可以随意变化,要找的是最大公约数只要sum%x==0都是可以做到的
如下
特列:不过同时注意满足这个要求至少需要两位如果是一位的话答案就是固定的一了
void solve(){
cin>>n;
LL sum=0;
for(int i=1;i<=n;i++){
int x; cin>>x;
sum+=x;
}
if(n==1){
cout<<1<<endl;
return ;
}
int ans=0;
for(LL i=1;i*n<=sum;i++){
if(sum%i==0){
ans++;
}
}
cout<<ans<<endl;
return ;
}
E.漂亮数组
数组划分问题,我们要求的是k倍数的数组,那么直接从前面开始即可,一直统计前面出现的余数的出现,如果说加上后面这个数出现了前面出现过的数,或者说现在满足的那就是取到当前这个位置即可,一般的划分问题都是这样
void solve(){
cin>>n>>m;
map<LL,int> mp;
LL ans=0,res=0;
for(int i=1;i<=n;i++){
LL x; cin>>x;
x%=m;
ans=(ans+x)%m;
if(mp.count(ans) || ans==0){
ans=0;
res++;
mp.clear();
}
else mp[ans]++;
}
cout<<res<<endl;
return ;
}
F.来点每日一题
考虑到n的数据范围以及题目的要求我们不难想到这是一个动态规划问题,但是如何定义状态是个问题,我们发现当前为最小值不一定是被放弃的解,所以同时维护最小值和最大值,接着考虑如果定义整个状态可以想到表示从l,r中选k个数当前的最大和最小值注意一些没有状态的舍去,所以我们再定义一个表示以r结尾的最大值即可
LL dp[M][M][7][2];
LL a[M];
LL d[M];
void solve(){
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++)
for(int j=0;j<=n;j++)
for(int k=0;k<=6;k++){
dp[i][j][k][0]=1e18,dp[i][j][k][1]=-1e18;
}
for(int L=1;L<=n;L++){
for(int R=L;R<=n;R++){
dp[L][R][1][0]=min(dp[L][R-1][1][0],a[R]);
dp[L][R][1][1]=max(dp[L][R-1][1][1],a[R]);
for(int k=2;k<=6;k++){
if(R-L+1<k) break;
if(k%2==0){
dp[L][R][k][0]=min(dp[L][R-1][k-1][0]-a[R],dp[L][R-1][k][0]);
dp[L][R][k][1]=max(dp[L][R-1][k-1][1]-a[R],dp[L][R-1][k][1]);
}
else{
dp[L][R][k][0]=min({dp[L][R-1][k-1][0]*a[R],dp[L][R-1][k][0],dp[L][R-1][k-1][1]*a[R]});
dp[L][R][k][1]=max({dp[L][R-1][k-1][1]*a[R],dp[L][R-1][k][1],dp[L][R-1][k-1][0]*a[R]});
}
}
}
}
for(int R=1;R<=n;R++)
for(int L=0;L<R;L++)
if(R-L+1<=6) d[R]=max(d[R],d[L]);
else d[R]=max(d[R],d[L]+dp[L+1][R][6][1]);
cout<<d[n]<<endl;
return ;
}
G.数三角形(easy)
简单性质,首先理清楚题目意思什么样是符合要求的三角形,然后观察数据范围我们发现最下面的一行我们可以考虑使用前缀和维护,边的长度可以考虑暴力维护不会超时即可通过
void solve(){
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
cin>>s[i][j];
h[i][j]=h[i][j-1];
if(s[i][j]=='*') h[i][j]++;
}
int ans=0;
auto bfs = [&](int x,int y){
for(int i=1;i<=max(n,m);i++){
if(x+i>n || y-i<1 || y-i>m) break;
if(s[x+i][y-i]!='*' || s[x+i][y+i]!='*') break;
if(h[x+i][y+i]-h[x+i][y-i-1]==2*i+1){
ans++;
}
}
return ;
};
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(s[i][j]=='*') bfs(i,j);
cout<<ans<<endl;
return ;
}