UPC-ナイト(数学の基礎の組み合わせ、逆)

学習は、上流を漕ぎのようなものです

騎士

タイトル説明

チェスの駒- -二次元グリッドの原点(0,0)で騎士があります。
騎士は、正方形(I、J)であるとき、それは、(I + 1、J + 2)又は(I + 2、J + 1)に移動させることができます。
ではどのように多くの騎士が正方形(X、Y)に達することができる方法?
いくつかの方法が10モジュロ検索9 +7を。
制約
・1≤X≤10 6
・1≤Y≤10 6
・入力のすべての値が整数です。

エントリー

:入力は、次の形式で標準入力から与えられる
XY

輸出

(0,0)から(X、Y)に到達する騎士のために多くの方法を印刷し、10モジュロ9 +7を。

サンプル入力1

3 3

サンプル出力1

2

サンプル入力2

999999 999999

サンプル出力2

151840682

サンプル入力3

2 2

サンプル出力3

0

トピック効果
チェス、中国のチェスの騎士同様の動きが、その移動中には、2 + 1で
どの手段
右1空間に移動するには、前方2つの正方形を移動するために
行くために左に前方2つの正方形1個のスペースウォーク
バックグリッドの2つの正方形を行くには右取る
1つのスペース左に戻る二つの空間に行くことは
前方の1つのスペースを移動するために2つの正方形を行くために左
グリッドの2つの正方形行くに戻って左
前方の1つのスペースを移動するには、すぐに2つの正方形を
右にグリッドの後、前方二つのスペースに行く
8つの移動の合計
に示すように、
ここに画像を挿入説明
タイトルあなたがそのポイントに来ることができる騎士まだ(x、y)に(0,0)から計算したい、悲しいことに、これが唯一の右または乗るにすることができ上がる
に示すようにあるここに画像を挿入説明
10のすべてのプログラムの計算された数。9 7テイクI

アイデア解析
ここに画像を挿入説明
この質問と似た方法で、この男がBにAから行ってきましたが、それはどのように多くの点
で、彼は3段階まで行き、右のステップ5を取る必要があります。しかし、シャシ侯の不確実性への権利を取る
、我々はそこにあることを知っています

C 5 8 若しくは C 3 8 種類 その 56 種類 ケース 溶液のC_ {5} ^ {8}又はC_ {3} ^ {8}可能、即ち、56種類
、この質問は似ていますが、騎士を取るために、右または全部良いと言うすべてが2つの戦略、アップ散歩を右に上がるために2つを歩きましたこの質問は、選択したどのように多くなり、オプション1とオプション2

その後、我々は方程式を解くことができる
2M +①X = N -
M + 2N = Y②
私たちはXとYの値を決定することができること
により得ることができる
M =(2X-Y)/ 3
N- =(2Y-X)/ 3
その結果、もし、mおよびn 3溶液により何ら割り切れることを特定することはできない
が続くが、ここに画像を挿入説明
これは不可能に移動、即ちNてはならない、mは一定の負の値に直接アクセスすることはできません

後でによると、
C メートル n個 = n個 * メートル - 1 * n個 - メートル - 1 C_ {M} ^ {N} = N *(M!)^!{ - 1} *((NM)!)^ { - 1}
再度逆に従うことができる
10の反転素子9+7 Iが取る
それがXを作ることができる-1Xに相当する。1E9 + 5
合同モジュラス原理、(* B)%C
逆の後、変化に加えて乗算します。このように解けます

ACまでの時間

#include<iostream>
#include<algorithm>
#include<string.h>
#include<map>
#include<queue>
#include <stack>
#include<string>
#include<utility>
#include<math.h>
#include<stdio.h>
#define PI 3.1415926536
#pragma GCC optimize(2)
using namespace std;
typedef long long ll;
const ll ll_inf = 9223372036854775807;
const int int_inf = 2147483647;
const short short_inf = 32767;
const char char_inf = 127;
inline ll read() {
	ll c = getchar(), Nig = 1, x = 0;
	while (!isdigit(c) && c != '-')c = getchar();
	if (c == '-')Nig = -1, c = getchar();
	while (isdigit(c))x = ((x << 1) + (x << 3)) + (c ^ '0'), c = getchar();
	return Nig * x;
}
#define read read()
ll A = 1e9 + 7;
ll B = A - 2;
ll qpow(ll x, ll n, ll mod)
{
	ll res = 1;
	while (n > 0)
	{
		if (n & 1)res = (res * x) % mod;
		x = (x * x) % mod;
		n >>= 1;
	}
	return res;
}
ll fac(ll n)
{
	ll res = 1;
	for (int i = 1; i <= n; i++)
	{
		res *= i;
		res %= A;
	}
	return res;
}
int main()
{
	ll X, Y;
	X = read, Y = read;
	ll m, n;
	m = X + X - Y;
	n = Y + Y - X;
	if (m % 3 || n % 3 || m < 0 || n < 0)
	{
		cout << 0 << endl;
		return 0;
	}
	else
	{
		m /= 3;
		n /= 3;
		ll temp_a = fac(m + n) % A;
		ll temp_b = fac(n) % A;
		ll temp_c = fac(m) % A;
		ll ans = temp_a;
		temp_b = qpow(temp_b, B, A);
		ans = (ans * temp_b) % A;
		temp_c = qpow(temp_c, B, A);
		ans = (ans * temp_c) % A;
		cout << ans % A << endl;
	}
}

変更のほかに乗った後、データの爆発は逆を忘れて、開始することができませんでしたに対処する方法を知っていない逆階乗ませんでした。逆によると、組合せ論、合同定理型、迅速なパワー。この問題を解決することができます。

ボートのための苦いトラックの道路グラウンド、無限の学習があります。
公開された32元の記事 ウォン称賛12 ビュー1188

おすすめ

転載: blog.csdn.net/qq_35339563/article/details/104524878