[BZOJ 3907] [JZOJ 3431] 网格
2016-06-11 19:18
295 查看
Description
某城市的街道呈网格状,左下角坐标为A(0, 0),右上角坐标为B(n, m),其中n >= m。现在从A(0, 0)点出发,只能沿着街道向正右方或者正上方行走,且不能经过图示中直线左上方的点,即任何途径的点(x, y)都要满足x >= y,请问在这些前提下,到达B(n, m)有多少种走法。100%的数据中,1 <= m <= n <= 5 000
Analysis
因为我是蒟蒻,所以这道题我是暴力找规律,找着找着突然发现好像是两个组合数相减。。。但是比赛的时候没有打完。
好吧,其实可以推出来。
将直线向上平移一格, 则限制条件等价于不能碰到直线。
那么我们将终点按这条直线对称过去,找到一个对称点。
我们发现把起点走到对称点的路径再对称回来,路径即是一条不合法的路径。
所以方案数可以由无限制乱走的方案数-起点走到对称点的方案数。
推一推,就发现方案数就是组合数。(因为dp是杨辉三角)
最后答案为Cmn+m−Cm−1n+m
但是看一下数据范围,并且题目没有要求取余数,所以我们要打高精度了。
Code
#include<cstdio> #include<cstring> #include<algorithm> #define fo(i,a,b) for(int i=a;i<=b;i++) #define fd(i,a,b) for(int i=a;i>=b;i--) using namespace std; const int N=5010; int n,m,a[N*2]; struct bignum { int n,a ; bignum(){} bignum(int jy) { memset(a,0,sizeof(a)); a[n=1]=jy; } }c,e; void pre(int n,int z) { int x=n; for(int i=2;i*i<=n;i++) while(!(x%i)) { x/=i; a[i]+=z; } if(x>1) a[x]+=z; } void mul(bignum &c,bignum a,bignum b) { c=bignum(0); c.n=a.n+b.n-1; fo(i,1,a.n) fo(j,1,b.n) { c.a[i+j-1]+=a.a[i]*b.a[j]; c.a[i+j]+=c.a[i+j-1]/10; c.a[i+j-1]%=10; } while(c.a[c.n+1]) { c.n++; c.a[c.n+1]=c.a[c.n]/10; c.a[c.n]%=10; } } void qmi(bignum &a,int x,int n) { e=bignum(x); for(;n;n>>=1) { if(n&1) mul(a,a,e); mul(e,e,e); } } int main() { //the answer is c[n+m][m]-c[n+m][m-1] scanf("%d %d",&n,&m); pre(n-m+1,1); fo(i,m+1,n+m) pre(i,1); fo(i,2,n+1) pre(i,-1); c=bignum(1); fo(i,2,10000) if(a[i]) qmi(c,i,a[i]); fd(i,c.n,1) printf("%d",c.a[i]); return 0; }
相关文章推荐
- NestedScrollView实现
- 随机行走
- 为Java程序中添加播放MIDI音乐功能
- 在Ubuntu 14.04 上安装网易云音乐
- jvm 内存划分 栈区 堆区 方法区
- xml用于非结构数据检索技术
- ListView(2)SimpleAdapter与SimpleCursorAdapter详解
- Action实现ModelDriven,不能实例化所需类的问题
- 8255的0方式及应用
- 从认知角度去理解设计
- HTML5与HTML4的区别
- 1 << 4 表示什么意思
- xml用于提高代码可读性
- 从零开始山寨Caffe·拾贰:IO系统(四)
- iOS旋转 — 关于Transform的一点小事
- 腾讯17年暑期实习生笔试题 - 有趣的数字
- hibernate级联更新(会先查询被关联的数据)
- navicat执行sql文件失败
- 从零开始山寨Caffe·拾:IO系统(三)
- 从零开始山寨Caffe·玖:BlobFlow