.JPG 불멸의 제목
이분법을 만날 수있는 첫 번째 대답은,이 점은 나중에 Entscheidungsproblem되었다.
우리는 지금 생각했습니다 \ (N \ 배 중반 \) , 처음에 가득 형태 (\ 0) \ , 우리가 할 수있는 A의 때마다 \ (m \) 추가의 수 \ (1 \) , 필요한 최종 각 라인은 같을 수 없습니다.
이제 우리는 여전히 두 가지 조건이 위의 사항을 충족해야, 다른 관점에서, 우리는 라인으로 채우기 라인을 고려합니다.
최적 동작의 첫 번째 라인 만 \ (1 \) \ (1 \)가 충전되어, 다음 라인 \ (2 \) \ (1 \) ...
기호가있는 라인 \ (I \) \ (1 \) 의 경우, 총 것이다 \ (C_ {중간} ^ I \) 행의 각 열은 것보다 \ (C_ {중간} ^ { I-1} \)를 \ (1 \) , 조합의 수는 순환 될 수있는.
라인이 열을 참조하는 것만으로는 충분하지 않습니다 경우 측면은 하나가 될 것입니다 최대에, 그것을 만들 수 있습니다 더 \ (\ DisplayStyle \는 \ lceil \ FRAC {RES1 \ 타임즈 I} {MID}을 \ 바로 \ rceil \ 왼쪽) 있는지 확인하기 위해, (\ \ 제작 : RES2 \)
열이 충분하지 않은 경우 그렇지 않은 경우에 투표를 거부했다.
빈 줄이있는 경우 마지막으로, 참조
#include<iostream>
#include<cstdio>
#define int long long
using namespace std;
int T, n, m, ans, l, r, mid;
inline int read()
{
int res = 0; char ch = getchar(); bool XX = false;
for (; !isdigit(ch); ch = getchar())(ch == '-') && (XX = true);
for (; isdigit(ch); ch = getchar())res = (res << 3) + (res << 1) + (ch ^ 48);
return XX ? -res : res;
}
int check(int mid)
{
int C1 = mid, C2 = 1, res1 = n - 1, res2 = m;
for (int i = 1; i <= mid; ++i)
{
if (i > 1)
{
C1 = C1 * (mid - i + 1) / i;
C2 = C2 * (mid - i + 1) / (i - 1);
}
if (res1 < C1)return (res1 * i + mid - 1) / mid <= res2;
else if (res2 < C2)return 0;
res1 -= C1; res2 -= C2;
}
return !res1;
}
signed main()
{
cin >> T;
while (T--)
{
n = read(); m = read();
l = 0; r = n - 1;
while (l <= r)
{
mid = (l + r) >> 1;
if (check(mid))ans = mid, r = mid - 1;
else l = mid + 1;
}
cout << ans << '\n';
}
return 0;
}