第一周训练题集

P8682 [蓝桥杯 2019 省 B] 等差数列

题目描述

数学老师给小明出了一道等差数列求和的题目。但是粗心的小明忘记了一部分的数列,只记得其中 N 个整数。

现在给出这 N 个整数,小明想知道包含这 N 个整数的最短的等差数列有几项?

输入格式

输入的第一行包含一个整数 N。

第二行包含 N 个整数 A1​,A2​,⋯,AN​。(注意A1​∼AN​ 并不一定是按等差数列中的顺序给出 )。

输出格式

输出一个整数表示答案。

输入输出样例

输入 

5
2 6 4 10 20

输出 

10

这题的思路就是先用sort排序,然后从第二项开始到最后一项,也就是从A1到An-1,逐一比较与前一项之差,找出其中最小的值,就是等差数列的公差。

注意:公差为0的时候要特判,不然会陷入死循环导致TLE(我就是这里被卡了导致前几次提交都是90分qwq)

#include <bits/stdc++.h>
#define MAXN 100005

long long a[MAXN];
int n;

using namespace std;

int check(int a,int b,int d)
{
	int n=0;
	while(a+n*d<=b)   ++n;
	return n;
}

int main()
{
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
    }
    sort(a,a+n);
    int minn=10000000;
    for(int i=1;i<n;i++)
    {
    	if(a[i]-a[i-1]<minn)   minn=a[i]-a[i-1];
    }
    int res;
    if(minn==0)   res=n;
    else res=check(a[0],a[n-1],minn);
    cout<<res;
    return 0;
}

P1226 【模板】快速幂

题目描述

给你三个整数a,b,p,求 a^b mod p。

输入格式

输入只有一行三个整数,分别代表 a,b,p。

输出格式

输出一行一个字符串 a^b mod p=s,其中 a,b,p 分别为题目给定的值, s 为运算结果。

输入输出样例

输入 

2 10 9

输出 

2^10 mod 9=7

这题我一开始看到,头脑简单地以为直接暴力就可以,直到我看到了数据范围。。。尝试了各种方法都未果后,我开始研究起了题解,终于算是弄明白了一点快速幂

有一个公式很重要,会贯穿代码的始终

(a*b) mod c=(a mod c * b mod c)mod c;

先说第一种:

第一种是对a^b 进行拆分变成a^b =a^{b/2}*a^{b/2}*a^(b%2),然后使用递归的方法层层递进再一一回归,即可得到答案,代码如下:

#include <bits/stdc++.h>
#define MAXN 1000005

using namespace std;

long long a,b,p;

long long pow(long long base,long long tmp)
{
	if(tmp==1)   return base;
	else if(tmp==0)   return 1;
	else
	{
		long long ans=pow(base,tmp/2)%p;
		long long ans1=(ans%p*ans%p)%p;
		if(tmp%2==1)
		{
//			ans1=(ans1%p*base%p);
			ans1=(ans1%p*base%p)%p;
		}
		return ans1;
	}
}

int main()
{
	cin>>a>>b>>p;
	long long res=pow(a,b);
	cout<<a<<"^"<<b<<" mod "<<p<<"="<<res;
	return 0;
}

第二种是把指数进行拆解,比如3^{11}=3^{1}+3^{2}+3^{8}。11的二进制表示为1011,把1011和0001(即1)做与运算,可以看出指数为1的时候前面的系数为1,然后把1011右移一位变成0101再和0001做与运算,得到指数为2的时候前面的系数为1...以此类推指数为4的时候前面的系数为0,指数为8的时候前面的系数为1。记得做右移运算的时候要把指数翻个番,即b*=b。

第二种方法代码如下

#include <bits/stdc++.h>
#define MAXN 1000005

using namespace std;

long long a,b,p;

long long pow(long long base,long long B)
{
	long long ans=1,tmp=base;
	while(B)
	{
		if(B&1)
		{
			ans=(ans%p*tmp%p)%p;
		}
		tmp=(tmp%p*tmp%p)%p;
		B=B>>1;
	}
	return ans;
}

int main()
{
	cin>>a>>b>>p;
	long long res=pow(a,b);
	cout<<a<<"^"<<b<<" mod "<<p<<"="<<res;
	return 0;
}

要记得在相乘的运算中用上上面提到的公式

P2249 【深基13.例1】查找

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

输入格式

第一行 2 个整数 n 和 m,表示数字个数和询问次数。

第二行 n 个整数,表示这些待查询的数字。

第三行 m 个整数,表示询问这些数字的编号,从 11 开始编号。

输出格式

输出一行,m 个整数,以空格隔开,表示答案。

输入输出样例

输入 

11 3
1 3 3 3 5 7 9 11 13 15 15
1 3 6

输出 

1 2 -1 

这题同样给出两种做法,第一种是用二分的做法。由于数列是单调不减的,所以我们利用下标进行二分,然后将目标值与q[mid]进行对比。因为是要找出第一次出现的位置,所以当q[mid]=k而l<r时,令r=mid。输出时要把l+1

#include <bits/stdc++.h>
#define MAXN 1000005

using namespace std;

int n,m;
vector<int> q;

int main()
{
    cin>>n>>m;
    for(int i=0;i<n;i++)
    {
    	int tmp;
    	cin>>tmp;
    	q.push_back(tmp);
    }
    for(int i=0;i<m;i++)
    {
    	int k,res;
    	cin>>k;
    	int l=0,r=n-1,flag=0;
    	while(l<=r)
    	{
    		int mid=(l+r)>>1;
    		if(l<r)
    		{
    			if(q[mid]<k)   l=mid+1;
    			else if(q[mid]>=k)   r=mid;
    		}
    	    else
    	    {
    	    	if(q[l]==k)
    	    	{
    	    		flag=1;
    	    		break;
    	    	}
    	    	else   break;
    	    }
    	}
    	if(flag==1)
    	cout<<l+1<<" ";
    	else
    	cout<<-1<<" ";
    }
    return 0;
}

第二种做法就是利用vector的性质,用lower_bound函数找出容器中第一个大于k的数出现的位置,再将此位置的数与k进行对比,一致则输出下标+1,否则就输出-1。

#include <bits/stdc++.h>
#define MAXN 1000005

using namespace std;

int n,m;
vector<int> q;

int main()
{
    cin>>n>>m;
    for(int i=0;i<n;i++)
    {
    	int tmp;
    	cin>>tmp;
    	q.push_back(tmp);
    }
    for(int i=0;i<m;i++)
    {
    	int k,res;
    	cin>>k;
    	res=lower_bound(q.begin(),q.end(),k)-q.begin();
    	if(q[res]==k)
    	cout<<res+1;
    	else
    	cout<<-1;
    }
    return 0;
}

P1824 进击的奶牛

题目描述

Farmer John 建造了一个有 N(2≤N≤105) 个隔间的牛棚,这些隔间分布在一条直线上,坐标是 x1​,x2​,⋯,xN​(0≤xi​≤109)。

他的 C(2≤C≤N)头牛不满于隔间的位置分布,它们为牛棚里其他的牛的存在而愤怒。为了防止牛之间的互相打斗,Farmer John 想把这些牛安置在指定的隔间,所有牛中相邻两头的最近距离越大越好。那么,这个最大的最近距离是多少呢?

输入格式

第 11 行:两个用空格隔开的数字 N 和 C。

第 2∼N+1 行:每行一个整数,表示每个隔间的坐标。

输出格式

输出只有一行,即相邻两头牛最大的最近距离。

输入输出样例

输入 #1

5 3
1
2
8
4
9

输出 #1

3

这也是相当经典的一道题目。同样利用二分的方法,我们先假定一个距离mid,当两个隔间的距离<mid的时候,两只牛是不愿意住的。而当两个隔间的距离大于等于mid的时候,两只牛是很乐意住进去的,同时不要忘了把代表比较对象的cur=i

#include <bits/stdc++.h>
#define MAXN 100005

int a[MAXN];
int n,m;

using namespace std;

bool check(int mid)
{
    int cnt=1,cur=0;
    for(int i=1;i<n;i++)
    {
        if(a[i]-a[cur]<mid)  continue;
        cur=i;
        ++cnt;
    }
    return cnt>=m;
}

int main()
{
    cin>>n>>m;
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
    }
    sort(a,a+n);
    int l=0,r=a[n-1];      //l不是从a[0]开始,而是从0开始
    while(l+1<r)
    {
        int mid=(l+r)>>1;
        if(check(mid))
        {
            l=mid;
        }
        else
        {
            r=mid;
        }
    }
    cout<<l;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值