总结:
对于0基础的同学来说,前6题会做大部分就比较不错了,G题并不是难题,补题也需要会做,对于H、I,是针对有基础的同学出的题,0基础的同学没有学这2题的算法,可以自行学习或者暂时放弃这2题,确实比较有难度
A
本题签到,模拟即可
#include<bits/stdc++.h>
using namespace std;
string s;
int t;
void work(){
cin>>s;int ans=0;
for(int i=0;i<s.length();i++){
if(s[i]<='9' && s[i]>='0') ans++;//判断数字
}
cout<<ans<<'\n';
}
int main()
{
cin>>t;
while(t--) work();
return 0;
}
B
签到,高中应该都学过公式,或者使用循环
//code1
#include<bits/stdc++.h>
using namespace std;
long long a1,a2;
long long n;
int main(){
cin>>a1>>a2>>n;
long long d=a2-a1;
cout<<a1+(n-1)*d;
}
//code2
#include<bits/stdc++.h>
using namespace std;
int main()
{
int A1,A2,d,n;
cin>>A1>>A2>>n;
d=A2-A1;
for(int i=2;i<=n;i++){
A1+=d;
}
cout<<A1;
}
C
按题意模拟即可
//string
#include <bits/stdc++.h>
using namespace std;
string s;
int main()
{
while (getline(cin, s)) {
int maxu = 0;
for (int i = 0; i < s.length(); i++) {
maxu = max(maxu, (int)s[i]);
}
for (int i = 0; i < s.length(); i++) {
cout << s[i];
if (s[i] == maxu)
cout << "(max)";
}
cout << endl;
}
}
//char
#include <stdio.h>
int main()
{
char a[105];
while (scanf("%s", a) != EOF) {
int i;
char max = a[0];
for (i = 1; a[i] != '\0'; i++) {
if (max < a[i])
max = a[i];
}
for (i = 0; a[i] != '\0'; i++) {
if (a[i] != max)
printf("%c", a[i]);
else
printf("%c(max)", a[i]);
}
printf("\n");
}
return 0;
}
D
第 n n n年的牛,是前一年牛的头数,加上生下的头数,也就是能生产的母牛头数 ( n − 3 ) (n-3) (n−3)
//递归写法
#include <iostream>
using namespace std;
int f(int n)
{
if(n == 1)
return 1;
else if(n == 2)
return 2;
else if(n == 3)
return 3;
else return f(n-1) + f(n-3);
}
int main()
{
int m;
while (cin>>m)
{
if (m == 0) break;
cout<<f(m)<<endl;
}
return 0;
}
//递推写法
#include <bits/stdc++.h>
#define maxn 100
using namespace std;
int n, f[maxn];
int main()
{
f[0] = 1; f[1] = 1, f[2] = 2; f[3] = 3;
for (int i = 4; i <= 60; i++) {//打表
f[i] = f[i - 1] + f[i - 3];
}
while (1) {
cin >> n;
if (n == 0) break;
cout << f[n] << '\n';
}
}
E
这题卡空格,稍微有点恶心,需要处理一下行末空格否则会PE
输出杨辉三角,递推式:
f [ i ] [ j ] = f [ i − 1 ] [ j ] + f [ i − 1 ] [ j − 1 ] f[i][j]=f[i-1][j]+f[i-1][j-1] f[i][j]=f[i−1][j]+f[i−1][j−1]
#include <bits/stdc++.h>
using namespace std;
int n;
int tu[40][40];
int main()
{
for (int i = 1; i <= 50; i++) {//初始化边界全1
tu[i][1] = 1;
tu[i][i] = 1;
}
for (int i = 2; i <= 40; i++)
for (int j = 2; j < i; j++)
tu[i][j] = tu[i - 1][j] + tu[i - 1][j - 1]; //递推式
while (scanf("%d", &n) != EOF) {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++) {
cout << tu[i][j];
if (j != i) //最后不输出空格
cout << " ";
}
cout << endl;
}
cout << endl;
}
}
F
题意:
给定 T T T组数据,每组数据有一个输入为 N N N,输出第 N N N个不能被 3 3 3整除且末位不是 3 3 3的数。
因为 K < = 1000 K<=1000 K<=1000,枚举前1000个即可
#include <bits/stdc++.h>
using namespace std;
int t, k, cnt, a[100000];
bool check(int x)
{
if (x % 3 == 0 || x % 10 == 3)
return 0;
else
return 1;
}
int main()
{
cin >> t;
for (int i = 1; i <= 90000; i++) {
if (check(i))
a[++cnt] = i;
}
while (t--) {
scanf("%d", &k);
cout << a[k] << endl;
}
}
G
题意:
给出一个只包含01的字符串,要求你将他分为若干个子串,使得每个子串中最小的未出现的数的和最小。
题解:
思维题
结论一:这个和最大为2,因为整个字符串只由0和1组成
-
如果是若干个连续的1组成的子串,那么他产生的贡献为0。
-
如果是若干个连续的0组成的子串,那么他产生的贡献为1。
-
如果01混杂,那么产生的贡献为2
结论二:要把0和1分开来,连续0串的个数即为sum,且ans=min(2,sum)
#include<bits/stdc++.h>
using namespace std;
int main(){
int t;
cin>>t;
while(t--){
char s[100010];
cin>>s+1;
//输入s+1可以从1到n进行操作,比较方便,c写法:scanf("%s",s+1);
int n=strlen(s+1);
s[0]='1';//特判
int ans=0;
for(int i=1;i<=n;i++)
if(s[i]=='0'&&s[i-1]=='1')
ans++;
cout<<(ans>2?2:ans)<<endl;
}
return 0;
}
H(二分)
题意:
一共有
n
n
n个英雄,他们要去屠龙,他们有力量值。一共有
m
m
m条龙,他有攻击力和防御力,当英雄们决定去杀这条龙时,只能派一人去屠龙,剩下的要守城。屠龙者的力量值要大于等于龙的防御力,剩下守城的人的力量值之和要大于等于龙的攻击力。通过1金币可以增加任意英雄的1点力量值。现求最少需要多少金币,才能杀某条龙(每次屠龙都是独立的过程,之前加的力量值不会累加到下一次屠龙)。
思路:
运用
l
o
w
e
r
_
b
o
u
n
d
(
)
lower\_bound()
lower_bound()函数二分查找第一个力量值大于等于龙的防御力的英雄。
-
如果不存在这个人,也就是龙的甲太高了,直接派最后一个人氪金和他干,剩下的人看情况要不要氪金买甲。
-
如果这个人存在且至少存在一个人杀不动龙。那么就派他去屠龙,剩下的人去守城,但这样可能浪费很多屠龙者的力量值。因此我们再假设一种情况,让比他弱小一点点刚好杀不动龙的人去氪金屠龙,他留下来守城。比较这两种情况所需的金币数量。
-
如果所有人都能屠龙,就让最弱的人去,也不好存在可能浪费很多力量值的情况了,因为只可能浪费更多。
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define ll long long
ll LINF = 1ll << 60;
int n, m, a[200010];
signed main()
{
cin >> n;
int sum = 0;
for (int i = 1; i <= n; i++) {
cin >> a[i];
sum += a[i];//求和
}
sort(a + 1, a + 1 + n);
cin >> m;
int x, y;
for (int i = 1; i <= m; i++) {
cin >> x >> y;
int p = lower_bound(a + 1, a + 1 + n, x) - a;
if (!a[p]) {//所有人都不能杀龙,派最大的氪金去
cout << max((ll)0, y - (sum - a[n])) + x - a[n] << endl;
}else {
int k1 = max(y - (sum - a[p]), (ll)0);//当前能屠龙的人
int k2 = x - a[p - 1] + max(y - (sum - a[p - 1]), (ll)0);//上一个人氪金去
if (p == 1) k2 = LINF;//第一个人没有上一个人,特判
cout << min(k1, k2) << endl;
}
}
return 0;
}
I(区间DP)
思路:
跑一遍区间DP,状态转移方程为
d p [ i ] [ j ] = d p [ i + 1 ] [ j − 1 ] + a [ i ] ∗ b [ j ] + a [ j ] ∗ b [ i ] − a [ i ] ∗ b [ i ] − a [ j ] ∗ b [ j ] dp[i][j]=dp[i+1][j−1]+a[i]∗b[j]+a[j]∗b[i]−a[i]∗b[i]−a[j]∗b[j] dp[i][j]=dp[i+1][j−1]+a[i]∗b[j]+a[j]∗b[i]−a[i]∗b[i]−a[j]∗b[j]
把两端点换一下,找到最大值即可。
#include<bits/stdc++.h>
using namespace std;
const int N=5100;
typedef long long ll;
ll dp[N][N],a[N],b[N];
int main()
{
int n,sum=0;
cin>>n;
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n;i++)cin>>b[i];
for(int i=1;i<=n;i++)sum+=(a[i]*b[i]);
ll maxx=0;
for(int len=2;len<=n;len++){
for(int i=1;i+len-1<=n;i++){
int j=i+len-1;
dp[i][j]=dp[i+1][j-1]+a[i]*b[j]+a[j]*b[i]-a[i]*b[i]-a[j]*b[j];
maxx=max(maxx,dp[i][j]);
}
}
printf("%lld\n",sum+maxx);
}