第一周的题

本篇博客涉及欧几里得算法、快速幂算法、二分搜索和二分答案。本篇博客用于自己的学习,如有错误,希望各位大佬帮我指出错误(不要喷我),我也会虚心求教,及时改正。(如有雷同,大抵是巧合)

1、

题目:数学老师给小明出了一道等差数列求和的题目。但是粗心的小明忘记了一部分的数列,只记得其中 N 个整数。现在给出这 N 个整数,小明想知道包含这 N 个整数的最短的等差数列有几项?

思路:用到欧几里得算法      第一步先输入n和n个数并将这n个数储存到数组中,然后用sort函数对它们进行排序,然后分别求出这n个数相邻两数之间的差值,然后使用欧几里得算法求各元素差值的最大公约数(写一个函数)  ,因此就能求出等差数列的方差,并且最大数和最小数都已知,即可求出这个等差数列共有几个数

# include <bits/stdc++.h>
using namespace std;
long long gcd(long long a,long long b)
{
    if(b==0)
    return a;
    else 
    return gcd(b,a%b);
}
int main()
{
    long  long n,a,x;
    scanf("%lld",&n);
    long long num[n],dm[n-1];
    for(a=0;a<n;a++)
    {
        scanf("%lld",&num[a]);
    }
    std::sort(num,num+n);              //用sort函数排序
    for(int b=0;b<n-1;b++)
    {
        dm[b]=num[b+1]-num[b];       //求各元素差值
    }
    // 使用欧几里得算法求各元素差值的最大公约数  
    long long res = dm[0];  
    for (int i = 1; i < n-1; i++) {  
        res = gcd(res, dm[i]);  
    }  
    if(res==0)
    x=n;
    else
    x=(num[n-1]-num[0])/res+1;
    printf("%d",x);
    return 0;
}

2、

题目:给你三个整数 a,b,p,求 a^b mod p

思路:用到快速幂运算(数据过大,求模)     先分别输入三个数,因为a,b过大,直接算会爆,所以先 让a取余,然后判断b是否为奇数,并进行相应的快速幂运算,然后a平方取余(防止数据过大,平方后取余),然后让b除2,循环下去可以算出模(res)

#include <stdio.h>  
 
long long fastpower(long long a, long long b, long long mod) {  
    long long res = 1;  
    a%=mod;
    while (b!=0) {  
     if (b & 1) res = (res * a) % mod; // 如果b的二进制最后一位为1(b为奇数),那么累乘到结果中
        a = (a * a) % mod;                
        b >>= 1;                        // b右移一位 ,除2  
    }  
    return res;  
}  
  
int main() {  
    long long a, b, p;  
    scanf("%lld %lld %lld", &a, &b, &p); 
    if(b==0)
     printf("%lld^%lld mod %lld = %lld\n", a, b, p, 1%p);
     else
    printf("%lld^%lld mod %lld = %lld\n", a, b, p, fastpower(a, b, p));  
    return 0;  
}

3、用二分搜索

题目:输入 n 个不超过 10^9 的单调不减的(就是后面的数字不小于前面的数字)非负整数 a1,a2,…,an​,然后进行 m 次询问。对于每次询问,给出一个整数 q,要求输出这个数字在序列中第一次出现的编号,如果没有找到的话输出 −1 。

思路:先运用二分搜索找到要求的数(设它为x)(没找到就是-1),然后在上界和mid中间遍历找到第一个x(可能会有重复的数字,因此需要找到第一个数字)然后把第一个x对应的位置存起来,最后输出即可

# include <bits/stdc++.h>
using namespace std;
long long search(long long num[],long long len,long long key)                          //二分法
{
    long long low=0;                           //定义最小
    long long high=len-1;                     //定义最大
    long long mid;                           //定义中间
    while(low<=high)                  //二分法搜索
    {
        //mid=(low+high)/2;//可能会溢出
        mid=low+(high-low)/2;  //重点重点重点            找中间值
        if(key==num[mid])               //判断mid与key是否相等
        {for(long long a=low;a<=high;a++)
             {
                 if(key==num[a])
                 {
                 mid=a;           //找到第一个‘x’
                 break;
                }
             }
            return mid+1;  
        }  
        else if(key>num[mid])             //如果key>mid  则新区间为[mid+1,high]
            low=mid+1;
        else                                       //如果key<mid  则新区间为[low,mid-1]
            high=mid-1;
    }
    return -1;                             //如果数组中无目标值key,则返回 -1 ;
}
int main()
{
    long long n,m;
    scanf("%lld %lld",&n,&m);                 //输入n,m
    long long num[n],dm[m],cm[m];
    for(long long a=0;a<n;a++)
    {
        scanf("%lld",&num[a]);                 //输入n个数据
    }
    for(long long c=0;c<m;c++)
    {
        scanf("%lld",&cm[c]);                  //输入m个需要查找的数
    }
    for(long long b=0;b<m;b++)
    {
        dm[b]=search(num,n,cm[b]);     //找到它们的位置
    }
    for(long long d=0;d<m;d++)
    {
        printf("%lld ",dm[d]);                 //分别输出它们的位置
    }
    return 0;
}

4、二分答案

题目:Farmer John 建造了一个有 N(2≤N≤10^5) 个隔间的牛棚,这些隔间分布在一条直线上,坐标是 x1​,x2​,⋯,xN​(0≤xi​≤10^9)。他的 C(2≤C≤N)头牛不满于隔间的位置分布,它们为牛棚里其他的牛的存在而愤怒。为了防止牛之间的互相打斗,Farmer John 想把这些牛安置在指定的隔间,所有牛中相邻两头的最近距离越大越好。那么,这个最大的最近距离是多少呢?

思路:先找到上界和下界,然后二分法找到mid,并用judge检测mid是否为可行解,并储存,然后不断二分,找到最大的可行解

# include <bits/stdc++.h>
using namespace std;
long long num[100001],dm[100001];
bool judge (long long x,long long c,long long n)  //判断二分法的答案是否符合 
{
	long long a=1;
	long long b=num[1];
	for(long long m=2;m<=n;m++)   //当间隔为x时,判断能容下几头牛,并比较c和能容下的牛个数 
	{
		if(num[m]-b>=x)
		{
			b=num[m];
			a++;
		}
	}
	if(a>=c)
	    return true;
	else
	    return false;
}
int main()
{
    long long int n,c,b=1,answer=0;
	scanf("%lld %lld",&n,&c);
	for(long long a=1;a<=n;a++)
	{
		scanf("%lld",&num[a]);       //数组从1开始,便于二分计算 
	}                                
	sort(num,num+n);
	
	long long left=1,right=num[n],mid;
	
	while(left<=right)
	{
		mid=(right+left)/2;
		if(judge(mid,c,n))
		{
			answer=mid;    //如果为解,则储存该解 
			left=mid+1;
		}
		else{
			right=mid-1;         //二分法找解并找出最优解 
		    }
	}
	
	printf("%lld",answer);
	return 0;
}

  • 8
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值