计算机算法 实验四 分治

(1)打印 n = 2^ 𝑘 个选手的循环赛日程表。
#include<bits/stdc++.h>
using namespace std;
#pragma GCC optimize(2)
typedef long long LL;
void solve(int k){
	int i,j,m,temp;
	int a[100][100];
	int n=2;
	a[1][1]=1;a[1][2]=2;  //人数为2时,直接打印赛程安排
	a[2][1]=2;a[2][2]=1;
    for(m=1;m<k;m++)  
	{		
	   temp=n;
	   n=n*2;		
	   for(i=temp+1;i<=n;i++)  //左下角
	   {
		  for(j=1;j<=temp;j++)
		  {
			a[i][j]=a[i-temp][j]+temp;				
		  }
	   }
		
		for(i=1;i<=temp;i++)  //右上角
		{
			for(j=temp+1;j<=n;j++)
			{
				a[i][j]=a[i+temp][j-temp];			
			}
		}

		for(i=temp+1;i<=n;i++)  //右下角
		{
			for(j=temp+1;j<=n;j++)
			{
				a[i][j]=a[i-temp][j-temp];				
			}
		}

	}
	for(i=1;i<=n;i++)  //打印赛程安排
	{
		for(j=1;j<=n;j++)
		{
			printf("%d ",a[i][j]);
			if(j==n)
			{
				printf("\n");
			}
		}
	}
}
int main()
{
	while(1)
	{
	   int k;
	   cout<<"输入k 格式为n=2^k"<<endl;
	   cin>>k;
	   if(k!=0)
	   solve(k);
	}
	return 0;
}
(2)已知一个无序的序列,请用尽可能高效的方法,求其中第 k 大的数。
#include<bits/stdc++.h>
using namespace std;
#pragma GCC optimize(2)
typedef long long LL;
int a[100010],n,k;
int quick_sort(int l,int r,int k)  //快排
{
    if(l>=r)return a[l];
    int mid=a[l+r>>1];  //以mid为划分两个区域处理
    int i=l-1,j=r+1;
    while(i<j)
    {
        do i++;while(a[i]<mid);
        do j--;while(a[j]>mid);
        if(i<j)swap(a[i],a[j]);
    }
    int s=j-l+1; //左边区间有多少个数
    if(s>=k)return quick_sort(l,j,k);  //判断k在哪个区间,递归处理那一个区间即可
    else return quick_sort(j+1,r,k-s);
}
int main()
{
    cin>>n>>k;
    for(int i=0;i<n;i++)scanf("%d",&a[i]);
    cout<<quick_sort(0,n-1,n-k+1);  // 第k大数即是sort后第n-k+1个数字
    return 0;
}
(3)Alice 和 Bob 来到古老的金字塔,发现古代法老留下的两个数 a 和 b(a<b),传说如
果能够在机关启动前正确数出两个数字间 1 出现的次数,就可以得到法老的权杖。机会只有
一次,你可以帮助他们么?(一个一个数肯定是来不及的。。。)
不会分治,只会暴力
#include<bits/stdc++.h>
using namespace std;
#pragma GCC optimize(2)
typedef long long LL;
void solve()
{
    LL a,b,ans=0;
    cin>>a>>b;
    for(int i=a;i<=b;i++)
    {
        string s=to_string(i);
        int n=s.size();
        for(int i=0;i<n;i++)
        {
            if(s[i]=='1')ans++;
        }
    }
    cout<<ans;
}
int main()
{
    int T;
    T=1;
    while(T--)
    {
        solve();
    }
    return 0;
}
(4)Alice 晚上要去看电影,Bob 也要一起去。Alice 随手写了一串数,要 Bob 经过若干次
比较求出这里面最大的数 最小数,并且 Bob 的比较次数一定要尽量小,如果是你,需要
比较多少次呢?
#include<bits/stdc++.h>
using namespace std;
#pragma GCC optimize(2)
typedef long long LL;
typedef pair<int,int> PII;
vector<int> vala, valmax, valmin;
int maxo(vector<int> valmax, int& t)  //比较
{
	int q = valmax.size();
	int max = valmax[0];
	for (int i = 0; i < q - 1; i++)
	{
		++t;
		if (valmax[i] < valmax[i + 1])
			max = valmax[i + 1];
	}
	return max;
}

int mino(vector<int> valmin, int& t)  //比较
{
	int q = valmin.size();
	int min = valmin[0];
	for (int i = 0; i < q - 1; i++)
	{
		++t;
		if (valmin[i] > valmin[i + 1])
			min = valmin[i + 1];
	}
	return min;
}

int main()
{
	int val;
	int t = 0;
	int sign = 0;
	while (cin >> val)
	{
		vala.push_back(val);
	}
	int n = vala.size();
	if (n & 1)
	{
		n = n - 1;
		sign = 1;
	}
	for (int i = 0; i < n; i += 2)
	{
		if (vala[i] > vala[i + 1])  //分大数区小数区
		{
			++t;
			valmax.push_back(vala[i]);
			valmin.push_back(vala[i + 1]);
		}
		else
		{
			++t;
			valmax.push_back(vala[i + 1]);
			valmin.push_back(vala[i]);
		}
	}
	int max = maxo(valmax, t);
	int min = mino(valmin, t);

	if (sign == 1)
	{
		t += 2;
		if (max < vala[n - 1])
			max = vala[n - 1];
		if (min > vala[0])
			min = vala[0];
	}
	cout << t;
}

(5)设 n 是一个正整数,现在要求将 n 分成若干个自然数的和,且使这些自然数乘积之和
最大。
思路:将数字分解使得乘积最大,需要满足以下几点要求,
1.因子>1
2,因子互不相等
3.因子互相靠近
例子:

所以自然想到从2开始累加到接设最后有最大因子为m,使得最后一个留下来的数(这里是4)小于等于m,其实m可以由数学公式推导出来是 小于等于(sqrt(2 * n + 17 / 4) - 3 / 2),再想办法让剩下的均摊到每个因子上,所以从最大(也就是这里的最后)一个因子开始,依次加1,一直到m为0为止,得出我们想要的因子,经行一次累乘就求出答案了

#include<bits/stdc++.h>
using namespace std;
#pragma GCC optimize(2)
typedef long long LL;
typedef pair<int,int> PII;
void solve()
{
   int n;
   cin>>n;
   int len=0;
   int size=(sqrt(2*n+17/4)-3/2);
   int temp[100010];
   for(int i = 2; i <= n; i++)
   {
     	temp[len++] = i;
	    n-=i;
   }
   int m = n;
   for(int i=len-1; m-->0;i--)
       temp[(i+len)%len]++;
    int ans=1;
    for(int i=0;i<len;i++)
    {
        ans*=temp[i];
    }
    cout<<ans;
}
int main()
{
    int T;
    T=1;
    while(T--)
    {
        solve();
    }
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值