一、数圈圈(模拟,进制位)
任意门
我的写法:
#include <iostream>
#include <sstream>
#include <string>
#include <iomanip>
using namespace std;
string dec2hex(int i) //将int转成16进制字符串
{
stringstream ioss; //定义字符串流
string s_temp; //存放转化后字符
ioss << setiosflags(ios::uppercase) << hex << i; //以十六制(大写)形式输出,hex是十六进制的意思
//ioss << resetiosflags(ios::uppercase) << hex << i; //以十六制(小写)形式输出//取消大写的设置
ioss >> s_temp;
return s_temp;
}
int main()
{
int a ;
cin>>a;
string s= dec2hex(a) ;
int res=0;
for(int i=0;i<s.length();i++)
{
if(s[i]=='0'||s[i]=='4'||s[i]=='6'||s[i]=='9'||s[i]=='A'||s[i]=='D')
res++;
else if(s[i]=='8'||s[i]=='B')res+=2;
}
printf("%d",res);
return 0;
}
y总写法:
#include <iostream>
#include <sstream>
#include <string>
#include <iomanip>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int cnt[]={
1,0,0,0,
1,0,1,0,
2,1,1,2,
0,1,0,0
};
int main()
{
int n;
cin>>n;
if(!n)
{
cout<<1<<endl;
return 0;
}
else {
int res=0;
while(n)
{
res+=cnt[n%16];
n/=16;
}
cout<<res<<endl;
}
return 0;
}
二、农田灌溉(枚举、二分)
我的写法:
#include <iostream>
#include <sstream>
#include <string>
#include <iomanip>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int N=205;
int a[N];
int main()
{
int t;
cin>>t;
while(t--)
{
memset(a,0,sizeof a);
int n,k;
cin>>n>>k;
for(int i=1;i<=k;i++)
cin>>a[i];
int mk=0;
if(a[k]!=n)mk=n-a[k]+1;
else mk=1;
mk=max(a[1],mk);
if(k!=1)
for(int i=2;i<=k;i++)
mk=max((a[i]-a[i-1])/2+1,mk);
printf("%d\n",mk);
}
return 0;
}
小白的写法:
#include <iostream>
#include <sstream>
#include <string>
#include <iomanip>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int N=205;
int a[N];
int main()
{
int t;
cin>>t;
while(t--)
{
memset(a,0,sizeof a);
int n,k;
cin>>n>>k;
int b[n+1];
for(int i=1;i<=k;i++)
{
cin>>b[i];
a[b[i]]=1;
}
int left=b[1]-1,m=0;
for(int i=1;i<k;i++)
m=max(m,b[i+1]-b[i]-1);
if(m%2==1)
m++;
m=m/2;
int right=n-b[k];
int sum;
sum=max(left,max(m,right));
cout<<sum+1<<endl;
}
return 0;
}
这个上面注释掉的地方是我之前写的就是很迷糊,就是有点乱,把什么时候+1,什么时候-1弄得不太清。
y总写法:
#include <iostream>
#include <sstream>
#include <string>
#include <iomanip>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int N=210;
int a[N];
int main()
{
int t;
cin>>t;
while(t--)
{
memset(a,0,sizeof a);
int n,k;
cin>>n>>k;
for(int i=1;i<=k;i++)
cin>>a[i];
int res=0;
res=max(a[1],n-a[k]+1);
for(int i=1;i<k;i++)
res=max(res,(a[i]+a[i+1])/2-a[i]+1);
//这个就是如果是在中间就只用算到一边的距离就可以了
cout<<res<<endl;
}
return 0;
}
三、选取数对(前缀和,dp)
任意门
像这种题目,我们首先先思考一下能不能用贪心,如果不能用贪心呢,我们就用dp
闫氏dp分析法
一般下标是默认的一维,然后每有一个限制,咱们就加一维。这一道题限制了我们只能选择k个数,所以我们的第二维变成有多少个数被选择了。
y总写法:
#include <iostream>
#include <sstream>
#include <string>
#include <iomanip>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int N=5010;
typedef long long ll;
ll f[N][N],s[N];
int n,m,k;
int main()
{
scanf ("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
s[i]=s[i-1]+x;
}
memset(f,-0x3f,sizeof f);
for(int i=0;i<=n;i++)
f[i][0]=0;
for(int j=1;j<=k;j++)
{
ll maxf=0;
for(int i=j*m;i<=n;i++)
{
maxf=max(maxf,f[i-m][j-1]+s[i]-s[i-m]);
f[i][j]=maxf;
}
}
ll res=0;
for(int i=1;i<=n;i++)
res=max(res,f[i][k]);
printf("%lld\n",res);
return 0;
}
一个大佬的写法:(我觉得还是蛮好的)
思维都一样的,就是写法,仅仅写法!!
#include <iostream>
#include <sstream>
#include <string>
#include <iomanip>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int N=5010;
typedef long long ll;
ll f[N][N],a[N];
int n,m,k;
int main()
{
scanf ("%d%d%d",&n,&m,&k);
vector<long long>a(n+1);
for(int i=1;i<=n;i++)
{
cin>>a[i];
a[i]+=a[i-1];
}
f[0][0]=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=k;j++)
{
f[i][j]=f[i-1][j];
if(i>=m)f[i][j]=max(f[i][j],f[i-m][j-1]+(a[i]-a[i-m]));
}
}
cout<<f[n][k]<<"\n";
return 0;
}
总结
厉害的人的确很多,十分钟ak令我叹为观止,最后一道dp差一点就写出来了,的确,自己需要多锻炼锻炼,虽然那个dp的确简单,一看就会,但是一做就废我也是很无奈。