0
点赞
收藏
分享

微信扫一扫

计算机行业

大明宫 2024-06-17 阅读 27
算法c++

前言:

  今天晚上实验室的一场比赛,题目难度感觉还行,有几道题大家都没做出来,老规矩,这些没写出来的题都放在这,等我有能力补的时候再来写。

正文:

原比赛链接:(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 青铜门下(待补):

后记:

  最后剩下的考试不多了,也快要临近暑假了,暑假实验室有训练,我和两个队友也报了暑假牛客多校比赛(不知死活),最近会开始系统的来刷题了,希望自己能不要松懈,争取在暑假开始前把牛客上算法基础精选题单大致刷一边吧希望在这个暑假后自己的能力能得到长足的进步。

举报

相关推荐

0 条评论