假期的小contest(2023.1.9)

本文展示了多个编程题目的解题思路和参考代码,涵盖了暴力解法、二分查找、差分数组、KMP字符串匹配、01背包问题、高精度加法、贪心策略、快速幂运算以及利用位运算求二进制中1的个数等常见算法模板。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

2023001,卑微林克

2023002,米法——治疗之力

2023003,达尔克尔——鼓隆之力

2023004,力巴尔——凭风而起

2023005,乌尔波扎——雷神之力

2023006,有趣的加法

2023007,排队打水

2023008,快速幂求解

2023009,排列数字

2023010,求二进制中1的个数


2023001,卑微林克

简单题,暴力解题

参考代码:

#include <stdio.h>
int main()
{
    int n,a,b,i,j,k;
    scanf("%d %d %d",&n,&a,&b);
    int min=n,h,l;
    h=n/a;
    l=n/b;
    for(i=0;i<=h;i++){
        for(j=0;j<=l;j++){
            k=n-(i*a+j*b);
            if(k>=0&&min>k){
                min=k;
            }
        }
    }
    printf("%d",min);
    return 0;
}

2023002,米法——治疗之力

二分的直接应用,套模板,写对相应的check即可

参考代码:

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int n,k;
const int N=100010;
int h[N],w[N];
bool check(int x)
{
    int res=0;
    for(int i=0;i<n;i++)
    {
        res=res+(h[i]/x)*(w[i]/x);   //res为总共可以分的块数
        if(res>=k)  return true;
    }
    return false;

}
int main()
{
    cin>>n>>k;
    for(int i=0;i<n;i++)   cin>>h[i]>>w[i];
    
    int l=1,r=1e5;
    while(l<r)
    {
        int mid=l+r+1>>1;
        if(check(mid))   l=mid;     
        else r=mid-1;      //找到符合条件的最大值,因此选用此模板
    }
    printf("%d\n",l);
    return 0;
}

2023003,达尔克尔——鼓隆之力

差分模板题目

参考代码:

#include<iostream>
#include<algorithm>
using namespace std;
const int N=100010;
int n ,m;
int l,r,c;
int a[N],b[N];
void insert(int l,int r,int c)
{
    b[l]+=c;
    b[r+1]-=c;
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)   cin>>a[i];
    for(int i=1;i<=n;i++)  insert(i,i,a[i]);  //构造差分数组
    while(m--)
    {
        cin>>l>>r>>c;
        insert (l,r,c);
    }
    for(int i=1;i<=n;i++)   a[i]=a[i-1]+b[i];
    for(int i=1;i<=n;i++) 
    {
        if(a[i]<0)  cout<<"0"<<" ";
        else   cout<<a[i]<<" ";
    }  
    return 0;
}

2023004,力巴尔——凭风而起

KMP主要分两步:求next数组、匹配字符串。个人感觉重点在于理解如何求出对应的next数组。

参考代码:

#include <iostream>
#include<algorithm>
using namespace std;
const int N = 100010, M = 1000010;

int n, m;
int ne[N];
char s[M], p[N];    //p模板串,s模式串,p去匹配s

int main()
{
    cin >> n >> p + 1 >> m >> s + 1;

    for (int i = 2, j = 0; i <= n; i ++ )
    {
        while (j && p[i] != p[j + 1]) j = ne[j];
        if (p[i] == p[j + 1]) j ++ ;
        ne[i] = j;
    }    //求next数组

    for (int i = 1, j = 0; i <= m; i ++ )
    {
        while (j && s[i] != p[j + 1]) j = ne[j];
        if (s[i] == p[j + 1]) j ++ ;
        if (j == n)
        {
            printf("%d ", i - n);
            j = ne[j];
        }
    }    //匹配

    return 0;
}

2023005,乌尔波扎——雷神之力

可以转化为01背包问题求方案数:

将总和 M看作背包容量;
将每个数 Ai 看作体积为 Ai 的物品;

参考代码:

#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 10010;

int n, m;
int f[N];

int main()
{
    cin >> n >> m;
    f[0] = 1;
    for (int i = 0; i < n; i ++ )
    {
        int v;
        cin >> v;
        for (int j = m; j >= v; j -- ) f[j] =f[j]+f[j - v];
    }

    cout << f[m] << endl;

    return 0;
}

2023006,有趣的加法

高精度加法模板题目

参考代码:

#include<bits/stdc++.h>
#include<vector>
using namespace std;

vector<int> add(vector<int> &A,vector<int> &B)
{
	vector<int> C;
	
	int t=0;//进位 
	for(int i=0;i<A.size()||i<B.size();i++)
	{
		if(i<A.size()) t+=A[i];
		if(i<B.size()) t+=B[i];
		C.push_back(t%10);
		t/=10;
	}
	if(t) C.push_back(1);
	return C;
}
int main()
{
	string a,b;
	vector<int> A,B;
	cin>>a>>b;//a="123456"
	for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');//A="654321",将输入的数字位置颠倒
	for(int i=b.size()-1;i>=0;i--) B.push_back(b[i]-'0');
	
	vector<int> C =add(A,B);
	
	for(int i=C.size()-1;i>=0;i--) cout<<C[i];
	
	return 0;
}

2023007,排队打水

贪心思想的应用

参考代码:

#include <iostream>
#include <algorithm>

using namespace std;

const int N = 1e5 + 10;

typedef long long LL;

int t[N];

int main()
{
    int n;
    cin>>n;
    for (int i = 0; i < n; i ++ )   cin>>t[i];

    sort(t, t + n);

    LL res = 0;
    for (int i = 0; i < n; i ++ )  res += t[i] * (n - i - 1);

    cout<<res<<endl;

    return 0;
}

2023008,快速幂求解

考察快速幂

参考代码:

#include<iostream>
using namespace std;
#define ull unsigned long long

ull quick_pow(ull a,ull b,ull p)
{
    if(b==0) return 1;
    a%=p;
    ull res=quick_pow(a,b>>1,p);

    if(b&1) return res*res%p*a%p;//b&1 判断b的二进制表示中第0位上的数是否为1,若为1,b&1=true,反之b&1=false,也可判断数字的奇偶性。 
    return res*res%p;
}
int main()
{
    int n;
    cin>>n;
    while(n--)
    {
        int a,b,p;
        cin>>a>>b>>p;
        cout<<quick_pow(a,b,p)<<endl;
    }
    return 0;
}

2023009,排列数字

dfs经典题目

参考代码:

#include<bits/stdc++.h>
using namespace std;

const int N = 10;
int path[N];//保存序列
int state[N];//数字是否被用过
int n;
void dfs(int u)
{
    if(u > n)//数字填完了,输出
    {
        for(int i = 1; i <= n; i++)//输出方案
            cout << path[i] << " ";
        cout << endl;
    }

    for(int i = 1; i <= n; i++)//空位上可以选择的数字为:1 ~ n
    {
        if(!state[i])//如果数字 i 没有被用过
        {
            path[u] = i;//放入空位
            state[i] = 1;//数字被用,修改状态
            dfs(u + 1);//填下一个位
            state[i] = 0;//回溯,取出 i
        }
    }
}

int main()
{

    cin >> n;
    dfs(1);
}

2023010,求二进制中1的个数

考察位运算

参考代码:

#include<bits/stdc++.h>
using namespace std;
int lowbit(int x){
    return x&(-x);
}
int main(){
    int n;
    cin>>n;
    while(n--){
        int x;
        cin>>x;
        int res=0;
        while(x) x-=lowbit(x),res++;
        cout<<res<<' ';
    }
    return 0;
}

前五道题目szw提供题解,后五道题目gmf提供题解!

 

以上就是关于此次的题解,以上代码仅供参考,答案不唯一,切勿照搬照抄!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值