前言:
今天晚上实验室的一场比赛,题目难度感觉还行,有几道题大家都没做出来,老规矩,这些没写出来的题都放在这,等我有能力补的时候再来写。
正文:
原比赛链接:(1条未读私信) 浙江广厦大学第七届程序设计比赛_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ (nowcoder.com)
A 种植所有植物所需时间:
#include<bits/stdc++.h>
using namespace std;
int main(){
ios::sync_with_stdio(false);
int n;long long ans=0;
cin>>n;
for(int i=1;i<=n;i++){
int x;
cin>>x;
ans+=x;
}
int cnt=ans;
ans/=50;
if(cnt%50!=0)ans++;
cout<<ans*5<<endl;
return 0;
}
简单求和后向上取整,注意数据量有1e7,记得取消同步流。
B 小马喝水:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
long double x, x2, y, y2;
int main(){
cin>>x>>y>>x2>>y2;
y=-y;
ll d=sqrt((x - x2)*(x - x2)+(y - y2)*(y - y2));
cout<<d;
return 0;
}
在坐标系下投影后求直线长度,注意数据范围很夸张,要用long double不然会出错。
C 菠萝蜜多斩(待补):
D 扫雷游戏:
#include <bits/stdc++.h>
using namespace std;
char a[1005][1005];
int b[1005][1005];
int main(){
int n,m;cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++)
cin>>a[i][j];
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(a[i][j]=='*') b[i][j]=-1;
else{
if(a[i-1][j]=='*') b[i][j]++;
if(a[i+1][j]=='*') b[i][j]++;
if(a[i][j-1]=='*') b[i][j]++;
if(a[i][j+1]=='*') b[i][j]++;
if(a[i-1][j-1]=='*') b[i][j]++;
if(a[i+1][j+1]=='*') b[i][j]++;
if(a[i+1][j-1]=='*') b[i][j]++;
if(a[i-1][j+1]=='*') b[i][j]++;
}}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++)
cout<<b[i][j]<<" ";
cout<<endl;
}
return 0;
}
简单暴力。
E 始皇一问:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
long long fac[2000005];
long long inv[2000005]; //inv[i]存储fac[i]的逆元
const long long mod = 998244353;
long long fastMul(long long a, long long b, long long mod){
long long res = 0;
while(b){
if (b & 1){
res = (res + a) % mod;
}
a = (a + a) % mod;
b >>= 1;
}
return res;
}
long long fastPowMod(long long a, long long n, long long mod){
if(n==0&&a!=0)return 1;
if(n!=0&&a==0)return 0;
long long base = a;
long long res = 1;
while(n){
if (n&1){
res = fastMul(res, base, mod);
}
base = fastMul(base, base, mod);
n >>= 1;
}
return res % mod;
}
void init(){
fac[0]=1;
for (int i=1;i<=2000000;i++){
fac[i]=(fac[i-1]*i)%mod;
}
inv[2000000]=fastPowMod(fac[2000000],mod-2,mod);
for (int i=2000000-1;i>=0;i--){
inv[i] = ((i + 1) * inv[i + 1]) % mod;
}
}
long long C(long long n, long long m){
return((fac[n] * inv[m])%mod*inv[n-m])%mod;
}
int main(){
init();
int t;
cin>>t;
while(t--){
int a,b;
cin>>a>>b;
cout<<C(a+b-2,min(a-1,b-1))<<endl;
}
return 0;
}
预处理阶乘和逆元,然后根据输入数据代入排列组合的公式,分号上面用阶乘,下面用逆元(因为mod为素数,直接用费马小定理求),最后得出答案。
F 压缩文章:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int main()
{
string s;cin>>s;
for(int i=0;i<s.size();i++){
int j=i;
while(s[i]==s[j]){
j++;
}
cout<<(j-i)<<s[i];
i=j-1;
}
return 0;
}
简单模拟,先输出次数,再输出该数。
G 原神启动 (hard):
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int a[10000005];
ll n,k,tot;
bool check(ll x){
int cnt=0,ans=0;
for(int i=1;i<=n;i++){
cnt+=a[i];
if(cnt>=x){
ans++;
cnt=0;
}
//cout<<x<<" "<<ans<<endl;
}
if(ans>=k)return true;
return false;
}
int main(){
cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>a[i];tot+=a[i];
}
if(tot<k){
cout<<-1<<endl;
return 0;
}
ll l=1,r=tot,mid;
while(l<r){
mid=l+r+1>>1;
if(check(mid))l=mid;
else r=mid-1;
// cout<<l<<" "<<r<<endl;
}
cout<<l<<endl;
return 0;
}
二分答案,check函数内用贪心思维,只要原石够就直接开抽,如果原石总数小于k就输出-1.
H 原神启动 (easy):
#include <bits/stdc++.h>
using namespace std;
const int N = 1e7 + 10;
typedef long long LL;
int main() {
int n, k;
cin >> n >> k;
LL res = 0;
for (int i = 1; i <= n; i++) {
int x;
scanf("%d", &x);
res += x;
}
if(res < k){
cout << "-1";
return 0;
}
int l = 1, r = res;
while (l < r) {
int mid = l + r + 1 >> 1;
if (res / mid >= k)
l = mid;
else
r = mid - 1;
}
cout << l;
return 0;
}
上题的简单版本,算出能抽的总次数即可。
I 古神话(待补):
J 青铜门下(待补):
后记:
最后剩下的考试不多了,也快要临近暑假了,暑假实验室有训练,我和两个队友也报了暑假牛客多校比赛(不知死活),最近会开始系统的来刷题了,希望自己能不要松懈,争取在暑假开始前把牛客上算法基础精选题单大致刷一边吧。希望在这个暑假后自己的能力能得到长足的进步。