学习犹如逆水行舟,不进则退
Knight
题目描述
There is a knight - the chess piece - at the origin (0,0) of a two-dimensional grid.
When the knight is at the square (i,j), it can be moved to either (i+1,j+2) or (i+2,j+1).
In how many ways can the knight reach the square (X,Y)?
Find the number of ways modulo 109+7.
Constraints
·1≤X≤106
·1≤Y≤106
·All values in input are integers.
输入
Input is given from Standard Input in the following format:
X Y
输出
Print the number of ways for the knight to reach (X,Y) from (0,0), modulo 109+7.
Sample Input 1
3 3
Sample Output 1
2
Sample Input 2
999999 999999
Sample Output 2
151840682
Sample Input 3
2 2
Sample Output 3
0
题目大意
在国际象棋中,骑士的走法类似中国象棋,不过,它的走法是2+1,
意思是
向前走两格向右走一格
向前走两格向左走一格
向后走两格向右走一格
向后走两格向左走一格
向左走两格向前走一格
向左走两格向后走一格
向右走两格向前走一格
向右走两格向前后一格
共八种走法
如图
题目想让你算出从(0,0)到(x,y)这个骑士可以走到那一点吗,可悲的是这个骑只能向右或者向上走
也就是如图
算出所有的方案数对109+7取余
思路分析
和这题方法类似,这个人从A走到B的话有多少种方法呢
也就是他一定要向右走5步,向上走3步。但是在啥时候走右走上这个不确定
那么就可以知道有
那么这题也类似,这个骑士只能采取向右走二向上走一或者向上走二向右走一的策略,所有说这就好整了,这题就变成了选择多少个方案1和方案2
那么我们就可以解方程
2m+n=X ①
m+2n=Y ②
这样我们就可以求出X和Y的值
可求得
m=(2X-Y)/3
n=(2Y-X)/3
所以说如果m和n不能被3整除那么一定无解
其次就是,
这种走法一定是不可能的,即不能直达使m和n的某个值为负值
之后根据
再根据逆元可
逆元对109+7取余
那么就可以使x-1等同于x1e9+5
根据同余模定理,(a*b)%c=a%c×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;
}
}
当时因为阶乘逆元爆数据不知道怎么处理才无从下手,忘记了逆元之后除变乘。根据逆元,组合数学,同余模定理,快速幂。可求解该题。
书山有路勤为径,学海无涯苦作舟。