一些有趣的思维题
这篇博客里收录的都是一些个人认为需要一些思维的题目,欢迎各位五分钟爆切这些题的大佬来暴打我。
1.AGC016B Colorful Hats
Step 1: 开上帝视角,发现共有
定义最大值
Step 2: 分类讨论。先考虑
Step 3:考虑
每次判断都是
AC代码:
#include<cstdio>
using namespace std;
int n,a[100005],mx,mn=1e9,x,y;
inline int max(int i,int j){return i>j?i:j;}
inline int min(int i,int j){return i<j?i:j;}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",a+i);
mx=max(mx,a[i]),mn=min(mn,a[i]);
}
if(mx-mn>1){printf("No\n");return 0;}
if(mx==mn){
if(mx==n-1){printf("Yes\n");return 0;}
if(mx<=n/2){printf("Yes\n");return 0;}
printf("No\n");return 0;
}
else{
for(int i=1;i<=n;i++)x+=(a[i]==mn?1:0),y+=(a[i]==mx?1:0);
if(x+1<=mx&&mx<=x+y/2){printf("Yes\n");return 0;}
else{printf("No\n");return 0;}
}
return 0;
}
2.AGC016C +/- Rectangle
这题据说在谷上原来是个黑,后来一路降降到了绿
最简单的思路,我们考虑把每个满足
但有以下反例:
1 3 1 2
按刚才的做法填完后的矩阵为 1 -2 1 ,和为零,不符合要求。考虑把不满足上面的条件的格子填上一个整数
AC代码:
#include<iostream>
#include<cstdlib>
#include<cstdio>
using namespace std;
const int mod=1e9;
int H,W,h,w,k;
int main(){
scanf("%d%d%d%d",&H,&W,&h,&w);
if(H%h==0&&W%w==0)return puts("No"),0;
printf("Yes\n");
k=1+rand()%(mod/(H*W));
for(int i=1;i<=H;i++){
for(int j=1;j<=W;j++){
int val=500;
if(i%h==0&&j%w==0)val=-500*(h*w-1)-1;
printf("%d ",val);
}
printf("\n");
}
return 0;
}
3.P4310 绝世好题
DP虐我千百遍,我爱DP如初恋
一个挺有意思的DP题。首先,我们可以轻易地想出类似于最长上升子序列的 90pts 的
一般的,这种带有位运算的题,突破口都是位运算。显然的,想要使两个数按位与后值不为零,则必须两个数对应位上都是1。我们考虑把一个数拆解成二进制数,设
接下来启动转移过程。这个算法是在线进行的。每读入一个数,记录一个值
#include<iostream>
#include<cstdio>
using namespace std;
const int N=100005;
inline int read()
{
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')f*=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
int n,f[35],ans;
int main()
{
n=read();
while(n--)
{
int x=read(),s=1;
for(int j=0;j<30;j++)
if(x&(1<<j))
s=max(s,f[j]+1);
for(int j=0;j<30;j++)
if(x&(1<<j))
f[j]=max(s,f[j]);
ans=max(ans,s);
}
printf("%d\n",ans);
return 0;
}