(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;
}