c++练习
二分法例题
例题:分巧克力
题目描述
儿童节那天有K位小朋友到小明家做客。小明拿出了珍藏的巧克力招待小朋友们。
小明一共有N块巧克力,其中第i块是Hi x Wi的方格组成的长方形。
为了公平起见,小明需要从这 N 块巧克力中切出K块巧克力分给小朋友们。切出的巧克力
需要满足:
形状是正方形,边长是整数
大小相同
例如:
一块6x5的巧克力可以切出6块2x2的巧克力或者2块3x3的巧克力。
当然小朋友们都希望得到的巧克力尽可能大,你能帮小Hi计算出最大的边长是多少么?
输入
第一行包含两个整数N和K。(1 <= N, K <= 100000)
以下N行每行包含两个整数Hi和Wi。(1 <= Hi, Wi <= 100000)
输入保证每位小朋友至少能获得一块1x1的巧克力。
输出
输出切出的正方形巧克力最大可能的边长。
样例输入
2 10
6 5
5 6
样例输出
2
#include <bits/stdc++.h>
using namespace std;
const int maxn=100005;
int Hi[maxn];
int Wi[maxn];
//maxn表示[]中的限制范围
int main()
{
int N,K;
scanf("%d%d",&N,&K);
for(int i=0;i<N;i++)
{
scanf("%d",&Hi[i]);
scanf("%d",&Wi[i]);
}//将N块儿巧克力的长度 宽度输出N次
int ans=0;
int l=1;//首段
int r=100000;//尾端
while(l<=r)
{
int mid=(l+r)/2;//中间指针
int cnt=0;//引入计数量
//check
for(int j=0;j<N;j++)
{
int temx=Hi[j]/mid;
int temy=Wi[j]/mid;
cnt+=(temx*temy);
}
if(cnt>=K)
{
l=mid+1;
}
else
{
r=mid-1;
}
}
cout<<min(l,r)<<endl;
}
前缀和差分例题
题目描述
对一个给定的自然数MM,求出所有的连续的自然数段,这些连续的自然数段中的全部数之和为M。
例子:
1998+1999+2000+2001+2002 = 10000,所以从1998到2002的一个自然数段为M=10000的一个解。
输入格式
包含一个整数的单独一行给出M的值(10≤M≤2,000,000)。
输出格式
每行两个自然数,给出一个满足条件的连续自然数段中的第一个数和最后一个数,两数之间用一个空格隔开,所有输出行的第一个按从小到大的升序排列,对于给定的输入数据,保证至少有一个解。
输入输出样例
输入
10000
输出
18 142
297 328
388 412
1998 2002
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 2000000;
long long a[MAXN+10];
int main()
{
int n;
cin >> n;
for (int i = 1; i <= MAXN; i++)
{
a[i] = a[i-1] + i;//前缀和
}
for (int i = 1; i <= MAXN; i++)
{
for (int j = i + 1; j <= MAXN; j++)
{
int sum = a[j] - a[i - 1];
if (sum == n)
{
cout << i << " " << j << endl;
}
else if (sum > n)//这一步很重要,不然会超时
{
break;
}
}
}
return 0;
}