首页 > 学院 > 开发设计 > 正文

CodeVS1515跳

2019-11-06 08:56:24
字体:
来源:转载
供稿:网友

链接

  http://codevs.cn/PRoblem/1515/

题解

  首先这是一张组合数表,f(i,j)=Cii+j   设m≤n,你会发现最优策略总是从(0,0)走到(n,0),然后再去(n,m),上述都是说的走直线。   将这张表用组合数的形式写出来,会发现   ans=n+C0n+C1n+1+C2n+2+...+Cmn+m=n+Cnn+Cnn+1+Cnn+2+...+Cnn+m=n+Cn+1n+1+Cnn+1+Cnn+2+...+Cnn+m=n+Cn+1n+2+Cnn+2+...Cnn+m=n+Cn+1n+3+Cnn+3+...+Cnn+m=...=n+Cn+1n+m+1=n+Cmn+m+1   因此对于这道题目   ans=max(n,m)+Cmin(n,m)n+m+1   网上老用什么lacus什么的,但完全没有必要…,题目中有个条件nm≤1012,那么min(n,m)≤106,使用高中数学中所说的“组合数的计算式”,是可以O(min(n,m))求出的。

代码

//组合数 #include <cstdio>#include <algorithm>#define ll long long#define maxn 3000000#define mod 1000000007using namespace std;ll n, m;inline void exgcd(ll a, ll b, ll &x, ll &y){ if(!b){x=1;y=0;return;} ll xx, yy; exgcd(b,a%b,xx,yy); x=yy, y=xx-a/b*yy;}ll inv(ll a, ll p){ ll x, y; exgcd(a,p,x,y); return (x+p)%p;}ll C(ll n, ll m){ ll ans=1, i, t; for(i=n;i>=n-m+1;i--)ans=ans*(i%mod)%mod; for(t=1,i=1;i<=m;i++)t=t*(i%mod)%mod; ans=ans*inv(t,mod)%mod; return ans;}ll calc(){ ll ans; ans=max(n,m)+C(n+m+1,min(n,m)); return ans%mod;}int main(){ scanf("%lld%lld",&n,&m); printf("%lld",calc()); return 0;}
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表