Week 1

本文介绍了在编程竞赛中处理等差数列问题的不同方法,如使用GCD求公差、辗转相除法和递归,以及快速幂的实现和二分查找优化查找操作。还涉及了一个关于奶牛问题的实例,展示了如何运用二分法求解最大值或最小值问题。
摘要由CSDN通过智能技术生成
1.P8682 [蓝桥杯 2019 省 B] 等差数列

        首先,将N个整数用sort由小到大排序。
        然后,希望找到最大的d,一开始用的是双层循环,直接爆了TLE,后来改用函数gcd求任意两项之间的最大公约数(更相减损法)。
        最后,用an=a1+(n-1)*d求项数。

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

int gcd(int x,int y)
{
    while(x!=y){
        if(x>y)
            x = x-y;
        else
            y = y-x;
    }
    return x;
}

int main()
{
    int n;
    cin>>n;
    int a[n];
    for(int i=0;i<n;i++){
        cin>>a[i];
    }
    sort(a,a+n);
    if(a[0]==a[n-1]){
        cout<<n;
        return 0;
    }
    int d = a[1]-a[0];
    for(int i=1;i<n;i++)
        d = gcd(d,a[i]-a[i-1]);//如果初始i=0,那么会出现a[0]-a[-1]的情况,导致数组越界
    //cout<<d;
    int ans = (a[n-1]-a[0])/d+1;
    cout<<ans;
    return 0;
}

另:(1) 求等差数列还可以用辗转相除法加递归。

int gcd(int x, int y)
{
    if (y == 0)
        return x;
    return gcd(y, x % y);
}

(2) if(d==0),即每一项的值都相等,则项数直接为n。(不提前说明#1会报RE)

2.P1226 【模板】快速幂

快速幂递归实现

int ksm(int a,int n)
{
    int ans;
    if(n==0) ans=1;
    else{
        ans = ksm(a*a,n/2);
        if(n%2==1) ans *= a;
    } 
    returm ans;
}

 显而易见,本题使用快速幂(喜欢循环)。
因为数据的范围能达到二的31次方,所以用long long搭配取模。

#include <iostream>
using namespace std;

long long b,p,k;

//循环快速幂
long long ksm(long long a,long long n){
	long long ans=1;
	while(n){
		if(n%2==1) ans = ans*a%k;//如果n为单数,乘到ans里面去,然后取模
		a =a*a%k;
		n /= 2;
	}
	return ans;
}

int main()
{
	cin>>b>>p>>k;
	long long res = ksm(b,p);
	res %= k;
	printf("%lld^%lld mod %lld=%lld", b, p, k, res);
	return 0;
}
3.P2249 【深基13.例1】查找

提示单调不减数列,明显可以使用二分查找降低时间复杂度,所以果断二分。
注意:因为这里的find函数中while循环结束条件是left==right,所以一旦找到与目标数字相同的数会自动覆盖掉原来的mid,使得最终结果一定第一个编号。

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

int a[1000010];//a[]表示n个整数
int n,m,k;

int find(int x)
{
    int left=1,right=n,mid;
    while(left<right){
        mid=(left+right)/2;
        if(a[mid]>=x)
            right = mid;
        else
            left = mid+1;
    }
    if(a[left]==x)
        return left;
    else
        return -1;
}

int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        cin>>a[i];

    while(m--){
        cin>>k;
        int ans = find(k);
        cout<<ans<<" ";
    }
    return 0;
}
4.P1824 进击的奶牛

 二分:最大值最小化或者最小值最大化

翻译题意:有n个坐标,存在x满足m(m<n)个坐标之间的距离最大,求x。

累了,直接上注释。

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

int a[100010];
int n,c,ans;

//判断x是否符合题意
bool check(int x)
{
    int now=0,num=1;//now:第一头奶牛肯定在第一个隔间,num:安排的奶牛数量
    for(int i=1;i<n;i++){
        if(a[i]-a[now]>=x){
            now=i;
            num++;
        }
    }
    return num>=c;//能安排的数量大于c,x成立,返回1;否则返回0
}

//二分找答案
void merge(int l,int r)
{
    if(l>r) return;
    int mid = (l+r)/2;//还可以mid=l+(r-l)/2,防溢出
    if(check(mid)){//如果mid满足,记录下来,然后在左边接着找
        merge(mid+1,r);
        if(ans>mid) ans = ans;
        else ans = mid;
    }
    else//反之,在右边找
        merge(l,mid-1);
}

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

    sort(a,a+n);
    merge(0,a[n-1]-a[0]);
    cout<<ans;
    return 0;
}


​

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

棠梨下

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值