网格
// 网格.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
/*
http://ybt.ssoier.cn:8088/problem_show.php?pid=1660
https://loj.ac/p/10238
原题来自:BZOJ 3907
某城市的街道呈网格状,左下角坐标为 A(0,0),右上角坐标为 B(n,m),其中 n≥m。现在从 A(0,0) 点出发,只能沿着街道向正右方或者正上方行走,且不能经过图示中直线左上方的点,即任何途径的点 (x,y) 都要满足 x≥y,请问在这些前提下,到达 B(n,m) 有多少种走法。
【输入】
仅有一行,包含两个整数 n 和 m,表示城市街区的规模。
【输出】
仅有一个整数和一个换行/回车符,表示不同的方案总数。
【输入样例】
6 6
【输出样例】
132
【提示】
数据范围与提示:
对于全部数据,1≤m≤n≤5000。
*/
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100010;
int primes[N], cnt;
bool st[N];
int a[N], b[N];
void init(int n) {
for (int i = 2; i <= n; i++) {
if (!st[i]) primes[cnt++] = i;
for (int j = 0; primes[j] <= n / i; j++) {
st[primes[j] * i] = true;
if (i % primes[j] == 0) break;
}
}
}
int get(int n, int p) {
int s = 0;
while (n) {
s += n / p;
n /= p;
}
return s;
}
void mul(int r[],int &len, int x) {
int t = 0;
for (int i = 0; i < len; i++) {
t += r[i] * x;
r[i] = t % 10;
t /= 10;
}
while (t) {
r[len++] = t % 10, t /= 10;
}
}
int C(int x, int y, int r[N]) {
int len = 1;
r[0] = 1;
for (int i = 0; i < cnt; i++) {
int p = primes[i];
int s = get(x, p) - get(y, p) - get(x - y, p);
while (s--) mul(r,len, p);
}
return len;
}
void sub(int a[], int al,int b[],int bl) {
for (int i = 0,t=0; i < al; i++)
{
a[i] -= t+b[i];
if (a[i] < 0) { a[i] += 10, t = 1; }
else t = 0;
}
}
int main()
{
init(N-1);
int n, m;
cin >> n >> m;
int al = C(n + m, m, a);
int bl =C(n + m, n + 1, b);
sub(a, al, b, bl);
int k = al - 1;
while (!a[k] && k > 0) {k--;}
while (k >= 0)printf("%d", a[k--]);
return 0;
}
作 者: itdef
欢迎转帖 请保持文本完整并注明出处
技术博客 http://www.cnblogs.com/itdef/
B站算法视频题解
https://space.bilibili.com/18508846
qq 151435887
gitee https://gitee.com/def/
欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
如果觉得不错,欢迎点赞,你的鼓励就是我的动力
欢迎转帖 请保持文本完整并注明出处
技术博客 http://www.cnblogs.com/itdef/
B站算法视频题解
https://space.bilibili.com/18508846
qq 151435887
gitee https://gitee.com/def/
欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
如果觉得不错,欢迎点赞,你的鼓励就是我的动力
浙公网安备 33010602011771号