1032: 找规律II
时间限制: 1 Sec 内存限制: 128 MB[ 提交 ][ 状态 ][ 讨论版 ]
题目描述
现有数阵如下:
![](https://i-blog.csdnimg.cn/blog_migrate/e7f38736162e09c02ca80d3dee046485.png)
求这个数阵的第n行m列是多少(行列标号从1开始)
结果对10007取模
输入
多组数据,每组数据一行,包含两个整数n,m(1<=n<=m<=10^18)
输出
每组数据输出一行,为数阵中第n行m列对10007取模后的值。
样例输入
1 1
1 2
1 3
样例输出
1
2
3
很容易就能看出是结果组合数,所以直接套用Lucas模版即可
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const LL MOD=10007;
LL n,m;
LL quick_pow(LL a, LL b) {
LL ans = 1;
a %= MOD;//防止指数为0时,返回未取模的结果
while(b!=0) {
if((b & 1)==1) {
ans = ans * a % MOD;
}
b >>= 1;
a = a * a % MOD;
}
return ans;
}
LL C(LL n, LL m) {
if(n < m) {
return 0;
}
if(n == m) {
return 1;
}
if(m > n - m) {//利用组合数性质,减少运算次数
m=n - m;
}
LL ans, a = 1, b = 1;
for(int i=0; i<m; ++i) {
a = (a * (n - i)) % MOD;
b = (b * (m - i)) % MOD;
}
ans = (a * quick_pow(b, MOD-2)) % MOD;
return ans;
}
LL Lucas(LL n, LL m) {
LL ans=1;
while(m>0) {
ans=(ans*C(n % MOD, m % MOD)) % MOD;
n/=MOD;
m/=MOD;
}
return ans;
}
int main() {
LL n,m;
while(2==scanf("%lld%lld",&n,&m)) {
printf("%lld\n",Lucas(m,m-n));
}
return 0;
}