一、打包
题目链接:
http://lx.lanqiao.cn/problem.page?gpid=T2978
解法:
连续、最小最大值,很典型的贪心+二分题。
代码:
#include <bits/stdc++.h>
using namespace std;
int a[100008];
int n,m;
int result;
int check(int mid)
{
int rc=0;
int bao=1;//包裹数
int i;
for(i=1;i<=n;i++)
{
if(rc+a[i]<=mid)
rc=rc+a[i];
else
{
rc=0;
rc=rc+a[i];
bao++;
}
}
if(bao<=m)
return 1;
else
return 0;
}
void p(int l,int r)
{ int mid;
while(l<=r)
{
mid=(l+r)/2;
if(check(mid))
{
r=mid-1;
result=mid;
}
else
l=mid+1;
}
}
int main()
{
int i;
cin>>n;
int sum=0;
int max=0;
cin>>m;//m个包裹
for(i=1;i<=n;i++)
{
cin>>a[i];
sum=sum+a[i];
if(a[i]>max)
max=a[i];
}
p(max,sum);
printf("%d\n",result);
return 0;
}
二、约数个数
题目链接:
http://lx.lanqiao.cn/problem.page?gpid=T2606
解法:
原本还想用欧拉筛,结果一看数据1e7。正确的做法是看看前面的数是后面多少个数的约数。所以,题目不要想得太复杂,尽量往简单想。
代码:
#include <bits/stdc++.h>
using namespace std;
int main()
{
long long n;
cin>>n;
long long i;
long long sum=0;
for(i=1;i<=n;i++)
{
sum=(sum+n/i)%1000000007;
}
printf("%lld\n",sum);
return 0;
}
三、寻找三位数
题目链接:
http://lx.lanqiao.cn/problem.page?gpid=T2038
解法:
全排列模拟一下就可以。
代码:
#include <bits/stdc++.h>
using namespace std;
int a[9];
int sum1,sum2,sum3;
void dfs(int k)
{
int i;
if(k>=9)
{
sum1=a[0]*100+a[1]*10+a[2]*1;
sum2=a[3]*100+a[4]*10+a[5]*1;
sum3=a[6]*100+a[7]*10+a[8]*1;
if(sum2==2*sum1&&sum3==3*sum1)
printf("%d %d %d\n",sum1,sum2,sum3);
return;
}
for(i=k;i<9;i++)
{
swap(a[i],a[k]);
dfs(k+1);
swap(a[k],a[i]);
}
}
int main()
{
int i;
for(i=0;i<9;i++)
a[i]=i+1;
dfs(0);
return 0;
}
四、第二点五个不高兴的小明
题目链接:
http://lx.lanqiao.cn/problem.page?gpid=T770
解法:
我用的方法是动态规划。设i为当前所在的位置,j为当前所跳的次数,则dp[i][j]表示在i位置时,已经跳了j次的最大权值和。可列出动态规划公式:dp[i][j]=max(dp[i-1][j-1],dp[i-2][j-1],…,dp[i-p][j-1])+w[i]。答案为dp[n+1][t]。
代码:
好像写得有点麻烦,不过挺清晰,友友们可以给我提点建议。
#include <bits/stdc++.h>
using namespace std;
int a[1008];
int b[1008][1008];
int main()
{
int n,p,t;
int i,j,k;
cin>>n;
cin>>p;
cin>>t;
for(i=0;i<1008;i++)
{
for(j=0;j<1008;j++)
b[i][j]=-99999999;
}
b[0][0]=0;
for(i=1;i<=n;i++)
cin>>a[i];
for(i=1;i<=n;i++)
{
for(j=min(i,t-1);j>=1;j--)
{ if(i-j*p>0)
break;
int max=-99999999;
for(k=1;k<=p;k++)
{
if(i-k<0)
break;
if(b[i-k][j-1]>max)
{
max=b[i-k][j-1];
b[i][j]=max+a[i];
}
}
}
}
int max=-99999999;
for(k=1;k<=p;k++)
{ if(n+1-k<0)
break;
if(b[n+1-k][t-1]>max)
max=b[n+1-k][t-1];
b[n+1][t]=max;
}
printf("%d\n",b[n+1][t]);
return 0;
}
总结
已经坚持二十多天了呢。接下来,需要好好巩固薄弱点以及复习知识点和错题啦!