2017山东省-D-Hex

来源:互联网 发布:编程语言进化 编辑:程序博客网 时间:2024/06/10 06:05

利用 (1,1)+x*(1,0)+y*(2,1)+z*(1,1)=(a,b).
求得 x+2*y+z=a-1;y+z=b-1; 得 x+y=a-b; y+z=b-1 y<=min(a-b,b-1)

枚举y,解出,x,z,然后解出 c(x+y+z,x)*C(y+z,y)*C(z,z) ,表明走x个左方向 y个下方向和z个右方向有多少种方案, 用 res加上。



#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;typedef long long ll;ll fact[101010],inv[101010];const int mod=1e9+7;const int maxn=1e5+7;ll quickM(ll a, ll b){    ll base = a%mod, ans = 1;    while(b){        if(b&1) ans = ans*base%mod;        base = base*base%mod;        b >>= 1;     }    return ans;}void init(){    fact[0] = 1;    for(int i = 1; i <= maxn; ++i)    fact[i] = fact[i-1]*i%mod;    inv[maxn]=quickM(fact[maxn],mod-2);    for(int i=maxn-1;i>=0;i--)    {        inv[i]=inv[i+1]*(i+1);        inv[i]%=mod;    }}ll C(int n, int m){    return ((fact[n]*inv[m])%mod*(inv[n-m]))%mod;}int main(){    int a,b;    init();    while(cin>>a>>b)    {        long long res=0;        int n=min(a-b,b-1);        for(ll y=0;y<=min(a-b,b-1);y++)        {            ll z=b-1-y;            ll x=a-b-y;            res+=(C(z+y+x,x)*C(z+y,y))%mod;            res%=mod;        }        printf("%lld\n",res );    }}
给出蜂窝的坐标(x,y),可以推算出两个数据:
1,最大步数,为x-1,即为全部左走或者右走的步数;
2,距离(1,1)的横向偏移量,为(x+1-2*y)(设左偏为正)。
利用这两个数据,即可推算出结果:
首先考虑全部左走或右走,即最大步数的情况,设左走为a,右走为b,下走为c,可得a+b=x-1,a-b=x+1-2*y,c=0,解出a和b,这部分的答案即为A(a+b+c,a+b+c)/(A(a,a)*A(b,b)*A(c,c));
然后考虑每一步下走相当于一次左走加一次右走,则每次a--,b--,c++,直到a,b其中一个或者全部为0,对于每次操作,可得结果也为A(a+b+c,a+b+c)/(A(a,a)*A(b,b)*A(c,c)),
累加结果即可,取模问题也是用乘上乘法逆元再取模的方法解决。。不会乘法逆元的可以先去学习一下

#include <bits/stdc++.h>using namespace std;typedef long long LL;LL i,x,y,a,b,c,ans,p[112345],mod=1e9+7,n[112345];LL exgcd(LL a,LL b,LL &x,LL &y){if(!b){x=1,y=0;return a;}LL r=exgcd(b,a%b,x,y),temp=x;x=y,y=temp-a/b*y;return r;}LL cal(LL a,LL m){LL ans,x,y,gcd=exgcd(a,m,x,y);if(1%gcd)return -1;x*=1/gcd,m=abs(m),ans=x%m;if(ans<=0)ans+=m;return ans;}int main(){p[0]=1,n[0]=cal(p[0],mod);for(i=1;i<112345;i++)p[i]=(p[i-1]*i)%mod,n[i]=cal(p[i],mod);while(~scanf("%lld %lld",&x,&y)){ans=c=0,a=x-y,b=x-a-1;while(~a&&~b)ans=(ans+p[a+b+c]*n[a]%mod*n[b]%mod*n[c]%mod)%mod,a--,b--,c++;printf("%lld\n",ans);}return 0;}



原创粉丝点击