赛后感慨
其实要我说榜单有点歪,虽然第一题代码量很短,但其实思考这个答案还是挺费劲的(如果提前没有了解过海盗分金这个模型的话),反观F、J和I纯暴力题解决量却很少(我明明把A题面搞得那么长你们都读下来了,为什么这三个不读呢....),还是说真是蒙的,其实D是做的压轴,没想到还有人能写出来,强大
A 贪心的小L
如果读明白题会发现,其实这里对每个人只有给或没给,你给了他就支持,不给就不支持,因为换下一个人可能就不给你了。
作为第一继承人,他肯定想让你去世,换他分配,你给不给都是一样的,你需要的是给半数人,让他们支持你就可以了,这题被简化了可能大部分人都是蒙的n/2,他底层类似
1 2 3 4 5 6 7
0 1 0 1 0 1 0 这样交替给,对于1给不给可能都要让你去世,而对于二,如果你去世,他变成1,那么新船长肯定也不给他,这样交替着给,如果1当上船长,原先分配1的都变成0这样即为最佳安排情况,所以最终是n/2(早知道让你们写出来分配情况了,你们也太敢蒙了...)
cpp
void solve()
{
int n;
cin>>n;
cout<<(n/2)<<endl;
}
B 猫猫爱喵喵
这题就是很简单的根据给出的时间做if判断即可,没什么大难度,按照题意写代码即可
cpp
void solve()
{
int a,b;
char o;
cin>>a>>o>>b;
int sum=a-12;
if(sum<0)
{
cout<<"不管猫猫的事哦~\n";
}
else
{
int ans=0;
for(int i=0;i<sum;i++)
{
ans+=i+1;
}
ans+=min(sum+1,b);
cout<<ans<<endl;
}
}
C 宝石
首先观察题目公式,下面的最小公倍数和最大公约数乘积明显就是a×b,化简出来其实就是
|a^2 − b^2|,所以我们让最小和最大的搭配即可
cpp
void solve()
{
int n;
cin>>n;
for(int i=0;i<n;i++)
cin>>a[i];
sort(a,a+n);
int t;
cin>>t;
for(int i=0;i<t;i++)
{
cout<<a[n-i-1]*a[n-i-1]-a[i]*a[i]<<endl;
}
}
D 看星星的小X
差分算法题,其实三个问题已经提示了大体思路(以时间做下标对一整天做差分即可),会差分的做出来应该问题不大,有问题自己再想想
cpp
int to_seconds(const string &t)
{
int hh = stoi(t.substr(0,2));
int mm = stoi(t.substr(3,2));
int ss = stoi(t.substr(6,2));
return hh * 3600 + mm * 60 + ss;
}
void solve()
{
int n,a,b,c,d,e,f;
cin>>n;
string name,s,sstart,sfinish;
int ma=0;
while(n--)
{
cin >> s >> sstart >> sfinish;
int start = to_seconds(sstart);
int finish = to_seconds(sfinish);
diff[start]++,diff[finish+1]--;
int sum=(finish-start+1);
if(sum>ma)
{
name=s;
ma=sum;
}
else if(sum==ma)
{
name=min(name,s);
}
}
int ans=diff[0],single=0;
if(diff[0]==1)
single++;
for(int i=1;i<60*60*24;i++)
{
diff[i]+=diff[i-1];
if(diff[i]==1)
single++;
ans=max(ans,diff[i]);
}
cout<<name<<" "<<single<<" "<<ans;
}
E 你的名字?
要求可随意组合为目标串,只需要看他们含有的字符串一致不一致即可,方法很多,我这里直接排序看相同也是做法之一,也可以做桶之类的,解法很多
cpp
void solve()
{
int n;
string s1,s2;
cin>>n>>s1>>s2;
sort(s1.begin(),s1.end());
sort(s2.begin(),s2.end());
if(s1==s2)
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
F 善良的小X
题目数据很小啊,没打算考太难,按照题目意思直接O(n^2)枚举即可,最后输出最大值(为什么大家伙不写呢.....)
cpp
void solve()
{
int n,x;
cin>>n;
double ans=INT_MAX;
for(int i=0;i<n;i++)
{
cin>>a[i];
}
cin>>x;
for(int i=0;i<n;i++)
{
int cnt=0,sum=0;
for(int j=i;j<n;j++)
{
sum+=a[j];
cnt++;
if(cnt>=8)
{
double temp=sum*1.0/cnt;
if(temp-x>1e-5&&ans-temp>1e-5)
{
ans=temp;
}
}
}
}
if(ans==INT_MAX)
cout<<-1;
else
cout<<fixed<<setprecision(2)<<ans;
}
G 面向结果编程
很有意思的一道题,题目也提示了做法(预处理),这里用init函数先求出来对应正整数的对应质数数量,然后对于每一次样例不用再重复的求值,也就是原先需要处理t(样例数)次,其实只需要处理一次存下来即可,按照题意输出即可,可以学一下R这个格式输出(非常好用)
cpp
int pre[100005];
bool su(int x)
{
int e=sqrt(x);
for(int i=2;i<=e;i++)
{
if(x%i==0)
return 0;
}
return 1;
}
void init()
{
pre[1]=0;
for(int i=2;i<=1e5;i++)
{
pre[i]=pre[i-1]+su(i);
}
}
void solve()
{
int x;
cin>>x;
cout<<R"(#include<stdio.h>
int main() {
int n;
scanf("%d", &n);
if (n == 1) printf("0");)"<<endl;
for(int i=2;i<=x;i++)
{
cout<<" else if (n == "<<i<<") printf(\""<<pre[i]<<"\");"<<endl;
}
cout<<R"( return 0;
})"<<endl;
}
H 调用函数
首先观察题目其实也就发现对于每一个操作只有加减,所以对应的操作数其实不太重要,我们统计出来所有的加减,最后加上原来的数即可
cpp
signed main()
{
int t;
cin>>t;
while(t--)
{
int n;
string s;
cin>>n>>s;
int ans=0;
string p="";
for(int i=0;i<n;i++)
{
if(s[i]=='A')
ans+=11451400;
else if(s[i]=='B')
ans+=31415900;
else if(s[i]=='C')
ans-=27182800;
else if(s[i]=='D')
ans-=1638400;
else if(s[i]>='0'&&s[i]<='9'||s[i]=='-')
p+=s[i];
}
int k=stoll(p);
cout<<ans+k<<endl;
}
}
I day4-别让企鹅吃石头
数据范围同样不大,按照题意每次枚举每一个位置移动的概率(左,中,右)这样,最后统计最大输出即可
cpp
int main() {
int N, k;
double p, q;
cin >> N >> p >> q >> k;
int n = N * 2 + 1;
vector<double> a(n,0.0);
a[N] = 1.0;
for(int i = 0; i < k; ++i){
vector<double> dp(n, 0.0);
for (int j = 0; j < n; ++j) {
if (a[j] == 0) continue;
int pos = j - N;
if (pos == -N) {
dp[j] += a[j] * (1 - q);
dp[j + 1] += a[j] * q;
}
else if (pos == N) {
dp[j] += a[j] * (1 - p);
dp[j - 1] += a[j] * p;
}
else {
dp[j - 1] += a[j] * p;
dp[j + 1] += a[j] * q;
dp[j] += a[j] * (1 - p - q);
}
}
a = dp;
}
vector<int> t;
double ans = 0.0;
for (int i = 0; i < n; ++i) {
if (a[i] > ans) {
ans = a[i];
t.clear();
t.emplace_back(i - N);
}
else if (a[i] == ans) {
t.emplace_back(i - N);
}
}
for (auto& v : t) {
cout << v << " ";
}
printf("\n%.5lf", ans);
return 0;
}
J 善用魔法的小L
数据范围依旧很小,支持O(n^2),从每一个题的位置做反转,统计得分,依次枚举即可(代码写的长是后面写着写着乱了,其实还是挺简单的,提供思路,不要学我.....)
cpp
int a[1005][10];
int b[1005][10];
int c[10];
int con(int a[],int b[])
{
int cnt=0;
for(int i=0;i<4;i++)
{
cnt+=b[i];
}
if(!cnt)
return 0;
for(int i=0;i<4;i++)
{
c[i]=a[i]+b[i];
}
for(int i=0;i<4;i++)
{
if(c[i]==-1)
return 0;
}
for(int i=0;i<4;i++)
{
if(c[i]==1)
return 3;
}
return 6;
}
void solve()
{
int n;
cin>>n;
for(int i=0;i<n;i++)
{
for(int j=0;j<4;j++)
{
cin>>a[i][j];
}
}
for(int i=0;i<n;i++)
{
for(int j=0;j<4;j++)
{
cin>>b[i][j];
b[i][j]*=-1;
}
}
int ans=0;
for(int i=0;i<n;i++)
{
int temp=0;
for(int j=0;j<n;j++)
{
temp+=con(a[(i+j)%n],b[j]);
}
ans=max(ans,temp);
}
cout<<ans;
}
总结
不管怎么样,HAUE新生周赛到此结束,中间也有些乱子,不过最后还算是顺利结束。长达七周的比赛,能促进学习不少知识,也能让大家的大学生活多一些共同话题,建立一些羁绊,成长不少。一次的比赛结束不是完结,后续还有n次更难,更有含金量的比赛,继续加油。