羅区AT249黒茶(茶)
トピックリンク:羅区AT249黒茶(茶)
アルゴリズム 模拟
タグ:、二分
タイトル
タイトル説明
ある日、\(kagamiz \)以下の質問にお答えしようとしている間に、お茶を飲みながら:
2つの正の整数からなる正整数の群をこのように配置されている場合、\((M、N-)\)最初のいくつかのセットにおける列の数は?
\((1,1)、(2,1)、(1,2)、(3,1)、(2,2)、(1,3)、(4,1)、(3,2)、 (2,3)、(1,4)、(5,1)、... \)
彼は次の質問へのより深い考察があるので、この質問は、彼のためにあまりにも単純です。
ときに前記の列の数\(I \)番目のグループ\((a_iを、B_i)\) 、最初の\(J \)番目のグループ\((a_j、b_j)\ ) 場合、\((a_iを+ a_j、 b_i + b_j)\)最初の数セット内の列の数ですか?
あなたの仕事は、彼がこの質問に答えることです。
入力形式
入力ラインのみ、2つの正の整数\(I、J \) 。
出力フォーマット
出力は正の整数であり、示したときの最初の上述した一連の\(I \)番目のグループ\((a_iを、B_i)\) 、最初の\(J \)番目のグループ\((a_j、b_j)\ ) 、\((a_iを+ a_j、b_i + b_j)\)最初のいくつかのセットの列の数です。
サンプル入力と出力
入力#1
1 1
出力#1
5
入力#2
3 2
出力#2
13
入力#3
114 514
出力#3
1155
説明/ヒント
データ範囲:
- \(^i≥1,1≤j≤108 \) 、および\(I、Jは、\)正の整数です。
- \(i、jは\)と等しくてもよいです。
ソリューション:
まず、によって与えられた数にこの質問を見てみましょう。
\((1,1)、(2,1)、(1,2)、(3,1)、(2,2)、(1,3)、(4,1)、(3,2)、 (2,3)、(1,4)、(5,1)、... \)
私たちは見つけ、そしてなどができ(N \)\総数の- \(1 \ n)の統計は最初のいくつかのグループのために問い合わせることができるように、法律によると、右。
我々は、に組み合わさそれぞれに、観察を続けた後、\(N- \)基の数、から最初のものである\(nは- 1 \)の\(1 \)第二は正反対であるから、減少\(1 \)に(N - 1 \)\刻み、これが最初のいくつかの最初の数行(全て1つのラインとして見られるため同じ番号)としてカウントすることができます。
また、データのテーマの範囲のために(1≤J≤10 ^ 8 \)\我々が使用することを選んだので、明らかに私たちは、クエリの暴力は非常に、限られており、(前に測定されていない)の和である数列の和と半分の回答以下を達成するための具体的なコードを解決する方法:
long long getsum(ll q) // 等差数列求和
{
return 1ll * ((1 + q) * q) / 2;
}
void find(long long q) // 二分查找答案
{
ll l = 1, r = N + 1, mid;
while(l < r)
{
mid = (l + r) >> 1;
if (getsum(mid) >= q)
r = mid;
else
l = mid + 1;
}
yy = q - getsum(l - 1);
xx = l - yy + 1;
}
ACコード
#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
const int N = 1e8 + 10;
typedef long long ll;
int xx, yy;
long long getsum(ll q)
{
return 1ll * ((1 + q) * q) / 2;
}
void find(long long q)
{
ll l = 1, r = N + 1, mid;
while(l < r)
{
mid = (l + r) >> 1;
if (getsum(mid) >= q)
r = mid;
else
l = mid + 1;
}
yy = q - getsum(l - 1);
xx = l - yy + 1;
}
int main()
{
ll x, y;
scanf("%lld%lld", &x, &y);
find(x);
ll ax = xx, ay = yy;
find(y);
ll bx = xx, by = yy;
ll qx = ax + bx, qy = ay + by;
ll pos = qx + qy - 1;
pos = getsum(pos - 1) + qy;
printf("%lld\n", pos);
return 0;
}