20200328分治算法总结

归并排序(从小到大)

void merge_sort(int *A,int x,int y,int *T)
{
    if(y-x>1)
    {
        int m=x+(y-x)/2;    //划分
        int p=x,q=m,i=x;
        merge_sort(A,x,m,T);    //递归求解
        merge_sort(A,m,y,T);    //递归求解
        while(p<m||q>y)
        {
            if(q>=y||(p<m&&A[p]<=A[q]))
                T[i++]=A[p++];    //从左半数组复制到临时空间
            else T[i++]=A[q++];    //从右半数组复制到临时空间
        }
        for(i=x;i<y;i++) A[i]=T[i];    //从辅助空间复制回原数组
    }
}

1325:【例7.4】 循环比赛日程表
【题目描述】
设有NN个选手进行循环比赛,其中N=2M2M,要求每名选手要与其他N−1N−1名选手都赛一次,每名选手每天比赛一次,循环赛共进行N−1N−1天,要求每天没有选手轮空。

【输入】
输入:MM。
【输出】
输出:表格形式的比赛安排表。一行各数据间用一个空格隔开。
【输入样例】
3
【输出样例】
1 2 3 4 5 6 7 8
2 1 4 3 6 5 8 7
3 4 1 2 7 8 5 6
4 3 2 1 8 7 6 5
5 6 7 8 1 2 3 4
6 5 8 7 2 1 4 3
7 8 5 6 3 4 1 2
8 7 6 5 4 3 2 1


#include<iostream>
#define N 1025
using namespace std;
int m,n,k=1,half=1,i,j,f[N][N];
int main()
{
     cin>>m;
     n=1<<m;
     f[0][0]=1;
     while(k<=m)
     {
         for(i=0;i<half;i++)
             for(j=0;j<half;j++)
             f[i][j+half]=f[i][j]+half;
         for(i=0;i<half;i++)
             for(j=0;j<half;j++)
             {
                 f[i+half][j]=f[i][j+half];
                 f[i+half][j+half]=f[i][j];
             }
         half*=2;
         k++;
     }
     for(i=0;i<n;i++)
     {
         for(j=0;j<n;j++)
            cout<<f[i][j]<<" ";
         cout<<endl;
     }
     return 0;
}

1326:【例7.5】 取余运算(mod)
提交数: 6816 通过数: 3092
【题目描述】
输入b,p,kb,p,k的值,求bpmodkbpmodk的值。其中b,p,k×kb,p,k×k为长整型数。

【输入】
输入b,p,kb,p,k的值。
【输出】
求bpmodkbpmodk的值。
【输入样例】
2 10 9
【输出样例】
2^10 mod 9=7


#include<iostream>
#include<cstdio>
using namespace std;
int b,p,k,a;
int f(int p)
{
    if(p==0) return 1;
    int tmp=f(p/2)%k;
    tmp=(tmp*tmp)%k;
    if(p%2==1) tmp=(tmp*(b%k))%k;
    return tmp;
}
int main()
{
    cin>>b>>p>>k;
    int tmpb=b;
    b%=k;
    cout<<tmpb<<"^"<<p<<" mod "<<k<<"="<<f(p)<<endl;
    return 0;
}

1327:【例7.6】黑白棋子的移动
【题目描述】
有2n个棋子(n≥4)排成一行,开始位置为白子全部在左边,黑子全部在右边,如下图为n=5的情形:
○○○○○●●●●●
移动棋子的规则是:每次必须同时移动相邻的两个棋子,颜色不限,可以左移也可以右移到空位上去,但不能调换两个棋子的左右位置。每次移动必须跳过若干个棋子(不能平移),要求最后能移成黑白相间的一行棋子。如n=5时,成为:
○●○●○●○●○●
任务:编程打印出移动过程。

【输入】
输入n。
【输出】
移动过程。
【输入样例】
7
【输出样例】
在这里插入图片描述

#include<iostream>
using namespace std;
int n,step,ans;
char ch[101];
void print()
{
    int i;
    if(step<10) cout<<"step "<<step<<":";
    else cout<<"step"<<step<<":";
    if(step==1)
    {
        ch[2*n+2]='*';
        ch[2*n+1]='o';
    }
    for(i=1;i<=2*n+2;i++)
        cout<<ch[i];
    cout<<endl;
    step++;
}
void init(int n)
{
    int i;
    step=0;
    ans=2*n+2;
    for(i=1;i<=n;i++)
        ch[i]='o';
    for(i=n+1;i<=2*n;i++)
        ch[i]='*';
    for(i=2*n+1;i<=2*n+2;i++)
        ch[i]='-';
    print();
}
void move(int k)
{
    int j;
    for(j=0;j<=1;j++)
    {
        ch[ans+j]=ch[k+j];
        ch[k+j]='-';
    }
    ans=k;
    print();
}
void change(int n)
{
    int i,k;
    if(n==4)
    {
        move(4);
        move(8);
        move(2);
        move(7);
        move(1);
    }
    else
    {
        move(n);
        move(2*n-1);
        change(n-1);
    }
}
int main()
{
    cin>>n;
    init(n);
    change(n);
    return 0;
}

1328:【例7.7】光荣的梦想
【题目描述】
Prince对他在这片大陆上维护的秩序感到满意,于是决定启程离开艾泽拉斯。在他动身之前,Prince决定赋予King_Bette最强大的能量以守护世界、保卫这里的平衡与和谐。在那个时代,平衡是个梦想。因为有很多奇异的物种拥有各种不稳定的能量,平衡瞬间即被打破。KB决定求助于你,帮助他完成这个梦想。
一串数列即表示一个世界的状态。
平衡是指这串数列以升序排列。而从一串无序数列到有序数列需要通过交换数列中的元素来实现。KB的能量只能交换相邻两个数字。他想知道他最少需要交换几次就能使数列有序。

【输入】
第一行为数列中数的个数n,第二行为n ≤ 10000个数。表示当前数列的状态。
【输出】
输出一个整数,表示最少需要交换几次能达到平衡状态。
【输入样例】
4
2 1 4 3
【输出样例】
2


#include<iostream>
#include<cstdio>
using namespace std;
int temp[10001],a[10001],tot=0;
void asort(int left,int right)
{
    if(left==right) return;
    int mid=(left+right)/2;
    asort(left,mid);
    asort(mid+1,right);
    int p=left,i=left,j=mid+1;
    while(i<=mid&&j<=right)
    {
        if(a[i]>a[j])
        {
            tot=tot+mid-i+1;
            temp[p++]=a[j++];
        }
        else temp[p++]=a[i++];
    }
    while(i<=mid) temp[p++]=a[i++];
    while(j<=right) temp[p++]=a[j++];
    for(i=left;i<=right;i++)
        a[i]=temp[i];
}
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    asort(1,n);
    printf("%d",tot);
    return 0;
}

1234:2011
提交数: 4617 通过数: 1969
【题目描述】
已知长度最大为200位的正整数n,请求出2011n的后四位。

【输入】
第一行为一个正整数k,代表有k组数据(k≤200),接下来的k行,每行都有一个正整数n,n的位数≤200。
【输出】
每一个n的结果为一个整数占一行,若不足4位,去除高位多余的0。
【输入样例】
3
5
28
792

【输出样例】
1051
81
5521
TLE代码


#include<iostream>
#include<cmath>
using namespace std;
int n,ans=1,t;
int main()
{
    cin>>t;
    while(t--)
    {
        ans=1;
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            ans*=2011;
            ans%=10000;
        }
        cout<<ans%10000<<endl;
    }
}

AC代码

#include<iostream>
#include<cmath>
#include<cstring>
#include<string>
using namespace std;
int ans=1,t,len,cnt,i;
char ch[205];
int main()
{
    cin>>t;
    while(t--)
    {
        ans=0;
        cnt=2011;
        cin>>ch;
        len=strlen(ch);
        for(i=len-4;i<len;i++)
        {
            if(i>=0)
                ans=ans*10+ch[i]-'0';
        }
        for(i=1;i*2<=ans;i*=2)
        {
            cnt*=cnt;
            cnt%=10000;
        }
        for(;i<ans;i++)
        {
            cnt*=2011;
            cnt%=10000;
        }
        cout<<cnt%10000<<endl;
    }
    return 0;
}

1240:查找最接近的元素
【题目描述】
在一个非降序列中,查找与给定值最接近的元素。

【输入】
第一行包含一个整数n,为非降序列长度。1 ≤ n ≤ 100000。
第二行包含n个整数,为非降序列各元素。所有元素的大小均在0-1,000,000,000之间。
第三行包含一个整数m,为要询问的给定值个数。1 ≤ m ≤ 10000。
接下来m行,每行一个整数,为要询问最接近元素的给定值。所有给定值的大小均在0-1,000,000,000之间。
【输出】
m行,每行一个整数,为最接近相应给定值的元素值,保持输入顺序。若有多个值满足条件,输出最小的一个。
【输入样例】
3
2 5 8
2
10
5

【输出样例】
8
5

#include<iostream>
#include<bits/stdc++.h>
using namespace std;
int n,m,a[100005],s,half,Left,Right;
bool flag=false;
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    cin>>m;
    while(m--)
    {
        cin>>s;
        Left=1;
        Right=n;
        half=(Left+Right)/2;
        flag=false;
        while(Right-Left>1)
        {
            if(a[half]>s)
            {
                Right=half;
                half=(Left+Right)/2;
            }
            else if(a[half]<s)
            {
                Left=half;
                half=(Left+Right)/2;
            }
            else
            {
                flag=true;
                break;
            }
        }
        if(flag) cout<<a[half]<<endl;
        else if(fabs(s-a[Left])<=fabs(s-a[Right])) cout<<a[Left]<<endl;
        else cout<<a[Right]<<endl;
    }
    return 0;
}
发布了8 篇原创文章 · 获赞 12 · 访问量 178

猜你喜欢

转载自blog.csdn.net/weixin_46434074/article/details/105156839