启航组欢乐赛 题解
T1 买本子
这一道题我们可以考虑暴力分解:如果每一个包装所含本子的数量不能总共要买的本子数量整除的话,要买的包装总数要多一,然后求出各包装总共的钱数最后比大小即可。
#include<cstdio>
#include<cstring>
using namespace std;
int main(){
int n, q, w, e, r, t, y, ans;
scanf("%d %d%d %d%d %d%d",&n, &q, &r, &w, &t, &e, &y);
if(n % q) q = (n / q) + 1;
else q = n / q;
if(n % w) w = (n / w) + 1;
else w = n / w;
if(n % e) e = (n / e) + 1;
else e = n / e;
q *= r;
w *= t;
e *= y;
ans = q;
if(ans > w) ans = w;
if(ans > e) ans = e;
printf("%d\n", ans);
return 0;
}
T2 哥的八个猜想
专门开一个函数判断质数,然后按照 \(i\) 和 \(j\) 都是质数的条件暴力枚举即可。
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
bool p(int num){
for(int i = 2; i <= sqrt(num); i++)
if(num % i == 0) return false;
return true;
}
int main(){
int n,i,j;
cin >> n;
for(i = 2; i <= n / 2; i++){
j = n - i;
if(p(i) && p(j)){
cout << n << " = " << i << " + " << j << endl;
break;
}
}return 0;
}
T3 成绩排名
开一个结构体冒泡排序即可,也可以写一个cmp函数用sort。
#include<stdio.h>
struct jxj {
int yw;
int sx;
int yy;
int sum;
int id;
};
int main() {
struct jxj a[500],temp;
int i,j,n;
scanf("%d",&n);
for(i=1; i<=n; i++) {
scanf("%d%d%d",&a[i].yw,&a[i].sx,&a[i].yy);
a[i].sum=a[i].yw+a[i].sx+a[i].yy;
a[i].id=i;
}
for(i=1; i<n; i++)
for(j=1; j<=n-i; j++) {
if(a[j].sum<a[j+1].sum) {
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
} else if(a[j].sum==a[j+1].sum&&a[j].yw<a[j+1].yw) {
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
} else if(a[j].sum==a[j+1].sum&&a[j].yw==a[j+1].yw&&a[j].id>a[j+1].id) {
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
for(i=1; i<=5; i++)
printf("%d %d\n",a[i].id,a[i].sum);
return 0;
}
T4 蛇形矩阵
纯找规律题,简单的按照行数分类讨论一下即可。
#include<iostream>
#include<cstdio>
#include<iomanip>
#include<cstring>
using namespace std;
int main() {
int n,i,j,k,t = 0;
int a[21][21] = {0};
cin >> n;
for(k = 1; k <= n; k++){
if(k % 2 == 0) {
for(i = 1; i <= k; i++) {
j = n - k + i;
t++;
a[i][j] = t;
a[n + 1 - i][n + 1 - j] = n * n + 1 - t;
}
}else{
for(i = k; i >= 1; i--) {
j = n - k + i;
t++;
a[i][j] = t;
a[n + 1 - i][n + 1 - j] = n * n + 1 - t;
}
}
}
for(i = 1; i <= n; i++) {
for(j = 1; j <= n; j++)
cout << setw(5) << a[i][j];
cout << endl;
}
return 0;
}
T5 type
手写一个字符栈,写入就压栈,删除就弹栈。
#include<iostream>
#include<cstdio>
using namespace std;
int n,top;
char a[100001];
int main() {
scanf("%d",&n);
while(n--) {
char ch[2];
scanf("%s",ch);
if(ch[0]=='T')cin>>a[++top];
else if(ch[0]=='U') {
int x;
scanf("%d",&x);
top-=x;
} else {
int x;
scanf("%d",&x);
cout<<a[x]<<endl;
}
}
return 0;
}
T6 最优布线问题
最小生成树问题模板,直接跑一遍克鲁斯卡尔即可。
#include <cmath>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iomanip>
#include <iostream>
using namespace std;
int main() {
int g[201][201];
long long int minl[201];
bool u[201];
int n,i,j,k,tot;
memset(g,0xffffff,sizeof(g));
cin>>n;
for (i = 1; i <= n; i++)
for (j = 1; j <= n; j++)
cin>>g[i][j];
for (i = 2; i <= n; i++)
minl[i] = 0x5ffffff;
minl[1] = 0;
minl[0] = 0x5ffffff;
memset(u,true,sizeof(u));
for (i = 1; i <= n; i++) {
k = 0;
for (j = 1; j <= n; j++)
if ((u[j]) && (minl[j] < minl[k]))
k = j;
u[k] = false;
for (j = 1; j <= n; j++)
if ((u[j]) && (g[k][j] < minl[j]))
minl[j] = g[k][j];
}
tot = 0;
for (i = 1; i <= n; i++)
tot += minl[i];
printf("%d\n",tot);
return 0;
}
T7 迷宫
直接跑一遍DFS就能得出答案。
#include<iostream>
#include<cstring>
using namespace std;
int n,s;
bool b[13][13];
const int dx[8]={0,0,1,1,1,-1,-1,-1},
dy[8]={1,-1,1,0,-1,1,0,-1};
void go(int x,int y)
{
if (x==1 && y==n){
s++;
return;
}
int i,xx,yy;
for (i=0;i<=7;i++)
{
xx=x+dx[i];
yy=y+dy[i];
if (b[xx][yy])
{
b[xx][yy]=false;
go(xx,yy);
b[xx][yy]=true;
}
}
}
int main()
{
int i,j,x;
cin>>n;
memset(b,0,sizeof(b));
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
{
cin>>x;
b[i][j]=(x==0);
}
s=0;
b[1][1]=false;
go(1,1);
cout<<s<<endl;
return 0;
}
T8 S君的甜品店
Subtask 1:
直接暴力枚举即可,预计得分 20 分。
Subtask 2:
使用 \(O(n^3)\) 的算法枚举出从 \(i\) 到 \(j\) 的每个区间(\(all_{i,j}\))然后用 \(dp_i=max(dp_i,dp_{j-1}+all_{j,i})\) 的状态转移方程求出最大值。
for(int i=1;i<=n;i++){
for(int j=i;j<=n;j++){
int f=1;
for(int k=i;k<=j;k++)
f=f*a[k]%19260817;
all[i][j]=f;
}
}
for(int i=1;i<=n;i++)
for(int j=1;j<=i;j++)
dp[i]=max(dp[i],dp[j-1]+all[j][i]);
预计得分50分。
Subtask 3:
我们可以发现一个性质,就是 \(all_{i,j}=all_{i,j-1}\times a_j\) ,即可以由前一个状态转移过来,我们就可以在 \(O(n^2)\) 的时间复杂度内预处理了。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=19260817;
ll a[10005],dp[10005],all[10005][10005];
int main() {
int n,f=1;
cin>>n;
for(int i=1; i<=n; i++) cin>>a[i];
for(int i=1; i<=n; i++) {
all[i][i]=a[i]%mod;
for(int j=i+1; j<=n; j++)
all[i][j]=all[i][j-1]*a[j]%mod;
}
for(int i=1; i<=n; i++)
for(int j=1; j<=i; j++)
dp[i]=max(dp[i],dp[j-1]+all[j][i]);
printf("%lld\n",dp[n]);
}
值得一提的是,如果你不开 long long 的话,预计和暴力老哥同分哦~