区间贪心算法
//优先左最大
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=110;//const后面带int
struct inteval{
double x;
double y;
}s[maxn];
bool cmp(inteval a,inteval b){
if(a.x!=b.x){
return a.x>b.x;//先从左端点从大到小
}
else{
return a.y<b.y;//再从右端点从小到大
}
}
int main(){
int n;
while(~scanf("%d",&n)){
for(int i=0;i<n;i++){
scanf("%lf %lf",&s[i].x,&s[i].y);//double输入
}
sort(s,s+n,cmp);//检查引用algorithm
int lx=s[0].x;
int count=1;
for(int i=1;i<n;i++){//从1开始
if(s[i].y<lx){
lx=s[i].x;
count++;
}
}
printf("%d\n",count);//不要忘了输出,输出不要忘了换行
}
return 0;
}
//优先右最小
#include <cstdio>
#include <algorithm>
using namespace std;//不能漏
struct inteval{
double x;
double y;
}s[110];
bool cmp(inteval a,inteval b){
if(a.y!=b.y){
return a.y<b.y;
}
else{
return a.x>b.x;
}
}
int main(){
int n=0;
while(scanf("%d",&n)!=EOF){
for(int i=0;i<n;i++){
scanf("%lf %lf",&s[i].x,&s[i].y); //double输入
}
sort(s,s+n,cmp);
int ly=s[0].y;
int count=1;
for(int i=1;i<n;i++){//从1开始
if(s[i].x>ly){
ly=s[i].y;
count++;
}
}
printf("%d\n",count);
}
return 0;
}
二分算法
#include <cstdio>
#include <algorithm>
using namespace std;
int binarySearch(int a[],int left,int right,int x){
//a严格递增,非递归,二分查等于
//序列中是否存在满足某条件的元素
//二分区间[left,right],传入初值[0,n-1];
int mid;
while(left<=right){//这里是为了判断区间是否存在
mid=(left+right)/2;//mid=left+(right-left)/2;
if(x<a[mid]){//严格递减:x>mid
right=mid-1;//right!=mid
}
else if(x>a[mid]){//严格递减:x<mid
left=mid-1;//left!=mid
}
else if(x==a[mid]){
return mid;
}
}
return -1;
}
int h_equal(int a[],int left,int right,int x){//大等于的第一个数
//上界为n,即所有数都小于x返回n
//二分区间[left,right],传入初值[0,n];
while(left<right){
//思路:假设存在,它该在的位置。因此是为了让循环一直执行
int mid=left+(right-left)/2;
if(a[mid]>=x){
right=mid;
}
else{
left=mid+1;
}
}
return left;//当right=left时停止,因此也可以return right,返回的都是夹出来的位置;
}
int higher(int a[],int left,int right,int x){//大于x的第一个数
//二分区间 [left,right],传入初值[0,n];
while(left<right){
int mid=left+(right-left)/2;
if(a[mid]>x){
right=mid;
}
else{
left=mid+1;
}
}
return right;//当right=left时停止,因此也可以return right,返回的都是夹出来的位置;
}
#define condition (1);
int conditionSolve(int left,int right){//寻找某序列中第一个满足某条件的位置
//以“从左到右先不满足,然后满足”为例
//二分区间[left,right],初值覆盖解的所有可能值
while(left<right){//对闭区间夹结果来说,left==right则找到唯一位置
//左开右闭:while(left+1<right)
int mid=left+(right-left)/2;
if(condition){
right=mid;//条件成立往左找
}
else{
left=mid+1;//条件不成立往右找
//左开右闭:left=mid;
}
}
return left;//返回夹出来的位置
//左开右闭:return left+1;
//求最后一个满足条件condition的,等于求第一个满足条件!condition的
}
int main(){
int n=0;
int a[20];
scanf("%d",&n);
for(int i=0;i<20;i++){
scanf("%d",&a[i]);
}
sort(a,a+n);
printf("%d\n",binarySearch(a,0,20,n));
return 0;
}
木棒切割问题
#include <cstdio>
int solve(int k,int a[],int n){
int l=0,x=k;
while(l<a[0]){
if(x>=k){
l++;
x=0;
for(int i=0;i<n;i++){
x+=a[i]/l;
}
}
else{
return --l;
}
}
return -1;
}
int main(){
int n=0,k=0;
scanf("%d%d",&n,&k);
int a[n]={0};
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
printf("%d",solve(k,a,n));
return 0;
}
快速幂算法
#include <cstdio>
typedef long long LL;
LL binaryPow(LL a,LL b){//递归写法
if(b==0){
return 1;
}
if(b&1){
return a*binaryPow(a,b-1);
}
else{
int m=binaryPow(a,b/2);
return m*m;
}
}
LL binaryPow2(LL a,LL b){//迭代写法
LL ans=1;
while(b>0){
if(b&1){
ans*=a;
}
a*=a;
b>>=1;//等同于b/=2;
}
return ans;
}
two pointers
#include <cstdio>
//利用问题与序列本身的特性,使用两个下标对序列进行扫描来降低算法复杂度
void twoPointers(int i,int j){
while(i<j){
if(i==j){
i++;
j--;
printf("(%d,%d)",i,j);
}
else if(i<j){
i++;
}
else{
j--;
}
}
}
int merge(int a[],int b[],int c[],int an,int bn){
int index=0,i=0,j=0;
while(i<an&&j<bn){
if(a[i]<=b[j]){
c[index++]=a[i++];
}
else{
c[index++]=b[j++];
}
}
while(i<an){
c[index++]=a[i++];
}
while(j<bn){
c[index++]=b[j++];
}
return index;
}
归并排序递归算法
#include <cstdio>
#include <cstring>
const int maxn=10010;
void merge(int a[],int l1,int r1,int l2,int r2){
int i=l1,j=l2,index=0;
int temp[maxn];
memset(temp,0,sizeof(temp));
while(i<=r1&&j<=r2){
if(a[i]<=a[j]){
temp[index++]=a[i++];
}
else{
temp[index++]=a[j++];
}
}
while(i<=r1){
temp[index++]=a[i++];
}
while(j<=r2){
temp[index++]=a[j++];
}
for(int i=0;i<index;i++){
a[l1+i]=temp[i];
}
}
void mergeSort(int a[],int l,int r){
if(l<r){
int mid=(l+r)/2;
mergeSort(a,l,mid);
mergeSort(a,mid+1,r);
merge(a,l,mid,mid+1,r);
}
}
int main(){
int n;
int a[maxn];
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
mergeSort(a,0,n);
for(int i=0;i<n;i++){
printf("%d ",a[i]);
}
}
归并排序非递归算法
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
void merge(int a[],int l1,int r1,int l2,int r2){
int i=l1,j=l2,index=0;
int temp[10010];
memset(temp,0,sizeof(temp));
while(i<=r1&&j<=r2){
if(a[i]<=a[j]){
temp[index++]=a[i++];
}
else{
temp[index++]=a[j++];
}
}
while(i<=r1){
temp[index++]=a[i++];
}
while(j<=r2){
temp[index++]=a[j++];
}
for(int i=0;i<index;i++){
a[l1+i]=temp[i];
}
}
void mergeSort(int a[],int n){
for(int step=2;step/2<=n+1;step*=2){
for(int i=0;i<n;i+=step){
int mid=i+step/2-1;
if(mid+1<=n){
merge(a,i,mid,mid+1,min(i+step-1,n-1));
}
}
}
}
int main(){
int n;
int a[10010];
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
mergeSort(a,n);
for(int i=0;i<n;i++){
printf("%d ",a[i]);
}
}
快速排序和随机选择
#include <cstdio>
#include <cstdlib>
#include <ctime>
int partition(int l,int r,int a[]){
int p=(int)(rand()*1.0/RAND_MAX*50000+10000);
int swap=a[l];
a[l]=a[p];
a[p]=swap;
int temp=a[l];
while(l<r){
while(l<r&&a[r]>temp){
a[l]=a[r];
}
while(l<r&&a[l]<=temp){
a[r]=a[l];
}
}
a[l]=temp;
return l;
}
void quickSort(int l,int r,int a[]){
if(l<r){
int pos=partition(l,r,a);
quickSort(l,pos,a);
quickSort(pos+1,r,a);
}
}
int randSelect(int a[],int l,int r,int k){
if(l==r){
return a[l];
}
int p=partition(l,r,a);
int m=p-l+1;//p是第m大的数
if(m==k){
return a[p];
}
else if(m<k){
randSelect(a,p+1,r,k-m);
}
else if(m>k){
randSelect(a,l,p-1,k);
}
}
分数的表示、化简、加减乘除
#include <cstdio>
#include <algorithm>
//一般情况下分子分母用long long型存储
struct Fraction{
int up;//不能直接int up=0;来初始化
int down;
}f1;
int gcd(int a,int b){
if(a<b){
int temp=a;
a=b;
b=temp;
}
if(b==0){
return a;
}
else{
return gcd(b,a%b);
}
}
Fraction fraReduction(Fraction f){//需要调用的函数要写在前面
if(f.down<0){
f.down=-f.down;
f.up=-f.up;
}
if(f.up==0){//正常运算分母不可能先为0,必是当分子为零时改分母
f.down=1;
}
else{
f.up/=gcd(abs(f.up),abs(f.down));//要加abs
f.down/=gcd(abs(f.up),abs(f.down));
}
return f;
}
Fraction fraAdd(Fraction f1,Fraction f2){
Fraction f;
f.up=f1.up*f2.down+f2.up*f1.down;
f.down=f1.down*f2.down;
return fraReduction(f);
}
Fraction fraMinu(Fraction f1,Fraction f2){
Fraction f;
f.up=f1.up*f2.down-f2.up*f1.down;
f.down=f1.down*f2.down;
return fraReduction(f);
}
Fraction fraMulti(Fraction f1,Fraction f2){
Fraction f;
f.up=f1.up*f2.up;
f.down=f1.down*f2.down;
return fraReduction(f);
}
Fraction fraDivide(Fraction f1,Fraction f2){
if(f2.up==0){
printf("Error.");
return f2;
}
else{
Fraction f;
f.up=f1.up*f2.down;
f.down=f1.down*f2.up;
return fraReduction(f);
}
}
void fraResult(Fraction f){
//考虑:化简,整数,假分数
f=fraReduction(f);
if(f.down==1){
printf("%d",f.up);
}
else{
if(f.down<f.up){
printf("%d %d/%d",f.up/f.down,f.up%f.down,f.down);
}
else{
printf("%d/%d",f.up,f.down);
}
}
}
int main(){
scanf("%d %d",&f1.up,&f1.down);
f1=fraReduction(f1);
printf("%d/%d\n",f1.up,f1.down);
}
简单素数表生成法
#include <cstdio>
#include <cmath>
bool isPrime(int n){
if(n<=1){
return false;
}
int sqr=(int)sqrt(n);
for(int i=2;i<=sqr;i++){//从2开始
if(n%i==0){
return false;
}
}
return true;
}
int prime[100010]={0};
int priNum=0;
int Find_prime(int n){
for(int i=2;i<=n;i++){
if(isPrime(i)){
prime[priNum++]=i;
}
}
}
int main(){
int n;
scanf("%d",&n);
Find_prime(n);
for(int i=0;i<priNum;i++){
printf("%d ",prime[i]);
}
return 0;
}
欧拉筛素数
#include <cstdio>
#include <cmath>
const int maxn=10010;
bool isnotPrime[maxn]={false};//不能初始化为true,否则其它还会是false
int prime[maxn]={0};
int priNum=0;
int olaPrime(int n){
for(int i=2;i<=n;i++){
if(isnotPrime[i]==false){
prime[priNum++]=i;
for(int j=i+i;j<=maxn;j+=i){
isnotPrime[j]=true;
}
}
}
}
int main(){//不能漏
int n;
scanf("%d",&n);
olaPrime(n);//不能漏
if(n>1){
for(int i=2;i<=n;i++){
if(isnotPrime[i]==false){
printf("%d ",i);
}
}
}
return 0;
}
大数加减乘除
#include <cstdio>
#include <cstring>
struct bign{
int d[1000];
int len;
bign(){
memset(d,0,sizeof(d));//只能用memset赋值
len=0;
}
};//分号不能少
bign bchange(char c[]){
bign a;
a.len=strlen(c);
for(int i=0;i<a.len;i++){
a.d[i]=c[a.len-i-1]-'0';
}
return a;
}
int compare(bign a,bign b){
if(a.len>b.len)return 1;
else if(a.len<b.len)return -1;
else{
for(int i=0;i<a.len;i++){
if(a.d[i]>b.d[i])return 1;
else if(a.d[i]<b.d[i])return -1;//不能漏
}
}
return 0;
}
bign badd(bign a,bign b){
int carry=0;//进位
bign c;
for(int i=0;i<a.len||i<b.len;i++){//不能仅是i<a.len
c.d[c.len++]=(a.d[i]+b.d[i]+carry)%10;//直接写上c.len++
carry= (a.d[i]+b.d[i]+carry)/10;
}
if(carry!=0){
c.d[c.len++]=carry;
}
return c;//不能漏
}
bign bsub(bign a,bign b){
bign c;
for(int i=0;i<a.len||i<b.len;i++){
if(a.d[i]<b.d[i]){
a.d[i+1]--;
a.d[i]+=10;
}
c.d[c.len++]=a.d[i]-b.d[i];
}
while(c.d[c.len-1]==0&&c.len>=2){
c.len--;
}
return c;
}
bign bmulti(bign a,int b){
int carry=0;
bign c;
for(int i=0;i<a.len;i++){
int temp=a.d[i]*b+carry;
c.d[c.len++]=temp%10;//不是c.d[i]
carry=temp/10;
}
while(carry!=0){
c.d[c.len++]=carry%10;//carry和temp不能混
carry/=10;
}
return c;//不能漏
}
bign bdivide(bign a,int b,int& r){
bign c;
c.len=a.len;//c也是从高到低
for(int i=a.len-1;i>=0;i--){
r=r*10+a.d[i];
c.d[i]=r/b;
r%=b;//不是r/=10
}
while(c.len>=2&&c.d[c.len-1]==0){
c.len--;
}
return c;
}
int main(){
char n1[1000]={' '};
char n2[1000]={' '};
int n3=0;
while(scanf("%s %s %d",n1,n2,&n3)!=EOF){
int r=0;
bign b1=bchange(n1);
bign b2=bchange(n2);
bign c=badd(b1,b2);//不能直接用n1,n2加
bign d;
if(compare(b1,b2)==-1){
d=bsub(b2,b1);
}
else{
d=bsub(b1,b2);//只允许b1>=b2
}
bign e=bmulti(b1,n3);
bign f=bdivide(b1,n3,r);//引用传参r
printf("%s+%s=",n1,n2);
for(int i=0;i<c.len;i++){//e.len什么的灵活调整
printf("%d",c.d[c.len-i-1]);
}
printf("\n%s-%s=",n1,n2);
if(compare(b1,b2)==-1){printf("-");}
for(int i=0;i<d.len;i++){
printf("%d",d.d[d.len-1-i]);
}
printf("\n%s*%d=",n1,n3);
for(int i=0;i<e.len;i++){
printf("%d",e.d[e.len-1-i]);
}
printf("\n%s/%d=",n1,n3);
for(int i=0;i<f.len;i++){
printf("%d",f.d[f.len-1-i]);
}
printf("...%d",r);
printf("\n");
}
return 0;
}
公约数公倍数
#include <cstdio>
int gcd(int a,int b){
if(b==0){
return a;
}
else{
return gcd(b,a%b);
}
}
int lcm(int a,int b){
return a/(gcd(a,b))*b;
}
int main(){
int a=0,b=0;
while(scanf("%d %d",&a,&b)){
printf("gcd(a,b)=%d\nlcm(a,b)=%d\n",gcd(a,b),lcm(a,b));
}
return 0;
}
欧几里得算法简单拓展
//a*x1+b*y1=gcd(a,b)
//b*x2+(a%b)*y2=gcd(a,b);
//a*x1+b*y1=b*x2+(a%b)*y2;(整除)
//a%b=a-(a/b)*b;
//a*x1+b*y1=b*x2+(a-(a/b)*b)*y2(整除)
//a*x1+b*y1=b*x2+a*y2-(a/b)*b*y2;
//a*x1+b*y1=a*y2+b*(x2-(a/b)*y2);
//x1=y2;
//y1=(x2-(a/b)*y2);
int exGod(int a,int b,int &x,int &y){
if(b==0){
x=1;y=0;
return a;
}
int g=exGod(b,a%b,x,y);
int temp=x;
x=y;//x1=y2;
y=temp-a/b*y;//y1=(x2-(a/b)*y2);
return g;
}
int main(){
int a=0,b=0,x=0,y=0;
while(~scanf("%d %d",&a,&b)){
printf(exGod(x,y));
}
}
n!问题
#include <cstdio>
int cal1(int n,int p){//n!中质因子p的个数
int ans=0;
while(n){
ans+=n/p;
n/=p;
}
return ans;
}
int cal2(int n,int p){
if(n<p)return 0;
else{
return n/p+cal(n/p,p);//(n/p)!中质因子p的个数
}
}
int main(){
int a=0,b=0;
while(~scanf("%d %d",&a,&b)){
printf("%d\n",cal(a,b));
}
return 0;
}
组合数计算
#include <cstdio>
long long c(long long n,long long m){
long long ans=1;
for(int i=1;i<=m;i++){
ans=ans*(n-m+i)/i;
}
return ans;
}
int main(){
long long n=0,m=0;
scanf("%lld %lld",&n,&m);
printf("%lld",c(n,m));
}