2016年暑假集训周赛#1题解

时间:2022-12-20 12:45:50

2016年暑假集训周赛#1


      周赛链接

Problem A:跑跑卡丁车系列之游戏下载


题目大意 :给出n个数,然后Q个询问,每次询问输入一个数字,输出n个数里面有多少个数小于等于它(总的减去大于这个数的)

思路:先排序,然后用upper_bound返回大于的第一元素

#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;

int a[10000010];
int main()
{
int n,Q,x;
while(~scanf("%d",&n))
{
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
sort(a,a+n); //排序
scanf("%d",&Q);
while(Q--)
{
scanf("%d",&x);
printf("%d\n",upper_bound(a,a+n,x)-a); //返回大于的第一个元素
}
}
return 0;
}




Problem B:跑跑卡丁车系列之登入密码----v1.0


题目大意 :给出一个字符串,可在任意位置添加字母,要求最少添加几个字母,能形成回文串

思路:将字符串翻转,求最长公共子序列,再用长度减去这个序列长度

#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;

int dp[510][510];
string s1,s2;
int main()
{
while(cin>>s1)
{
s2=s1;
reverse(s2.begin(),s2.end()); //翻转
memset(dp,0,sizeof(dp)); //初始化
int l=s1.length();
for(int i=1;i<=l;i++)
{
for(int j=1;j<=l;j++)
{
if(s1[i-1]==s2[j-1])
dp[i][j]=dp[i-1][j-1]+1; //求最长公共子序列
else
dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
}
}
printf("%d\n",l-dp[l][l]); //用长度减去最长公共子序列
}
return 0;
}




Problem C:跑跑卡丁车系列之登入密码----v2.0


题目大意 :同上

思路:利用滚动数组

#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;

int dp[2][5050];
char s1[5001],s2[5010];
int main()
{
while(~scanf("%s",s1))
{
memset(dp,0,sizeof(dp));
int l=strlen(s1);
for(int i=l-1;i>=0;i--)
s2[l-i-1]=s1[i];
s2[l]='\0';
int ans=0;
for(int i=1;i<=l;i++)
{
for(int j=1;j<=l;j++)
{
if(s1[i-1]==s2[j-1])
dp[i%2][j]=dp[(i-1)%2][j-1]+1; //滚动数组
else
dp[i%2][j]=max(dp[(i-1)%2][j],dp[i%2][j-1]);
if(dp[i%2][j]>ans)
ans=dp[i%2][j]; //存最大值 ,最长公共子序列
}
}
printf("%d\n",l-ans); //长度减去最长公共子序列长度
}
return 0;
}




Problem D/E:跑跑卡丁车系列之开齿轮----v1.0/2.0

题目大意 :合成一个齿轮需要n种材料,每种材料需要ai个,每种材料有bi个,可以使用k次技能,使用技能能免费获得一个某种材料

思路:用二分搜索答案

#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;

long long n,k,m,sum,a[100010],b[100010];
long long search(long long l,long long r)
{
while(l<=r)
{
m=(l+r)/2;
sum=0;
for(int i=1;i<=n;i++) //遍历每种材料是否满足
{
if(a[i]*m>b[i])
sum+=(a[i]*m-b[i]);
if(sum>k)
break;
}
if(sum==k)
return m;
else if(sum<k)
l=m+1;
else
r=m-1;
}
return r;
}
int main()
{
while(~scanf("%lld%lld",&n,&k))
{
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
for(int i=1;i<=n;i++)
scanf("%lld",&b[i]);
printf("%lld\n",search(1,2000000002)); //最多可以做这么多蛋糕
}
return 0;
}





Problem F:跑跑卡丁车系列之排车位----v1.0

题目大意 :有n*n的方格,k辆车,满足任意两辆车不在同一行,同一列.

思路:找规律,每次取模

#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;

int n,m;
long long a[32][32];
#define INF 1000000007
int main()
{
for(int i=1;i<=30;i++)
{
for(int j=1;j<=i;j++)
{
if(j==1)
a[i][j]=(i*i);
else
a[i][j]=(a[i][1]*a[i-1][j-1]/j%INF);
}
}
while(~scanf("%d %d",&n,&m))
{
printf("%lld\n",a[n][m]);
}
return 0;
}




Problem G:跑跑卡丁车系列之排车位----v2.0


题目大意 :同上

思路:上一题去掉取模.

#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;

int n,m;
long long a[32][32];
#define INF 1000000007
int main()
{
for(int i=1;i<=30;i++)
{
for(int j=1;j<=i;j++)
{
if(j==1)
a[i][j]=i*i;
else
a[i][j]=(a[i][1]*a[i-1][j-1]/j);
}
}
while(~scanf("%d %d",&n,&m))
{
printf("%lld\n",a[n][m]);
}
return 0;
}


美辰的水题:

Problem H:方巨的数学题_v1

Problem I:方巨的数学题_v2