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,求 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%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; }
第二种是把指数进行拆解,比如=
+
+
。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 个不超过的单调不减的(就是后面的数字不小于前面的数字)非负整数 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; }