HEX SDUT 3896 17年山东省赛D题
这个题是从矩形的左下角走到右上角的方案数的变形题,看来我对以前做过的题理解还不是太深,或者是忘了。对于这种题目,直接分析它的性质就完事了。从(1,1)走到(a,b)向左走的步数和向右走的步数是确定的,向下是代表向左向右各走了一步。细节:利用对称性,线性推逆元

对于每一种情况,向左下、向右下、向下的次数都是确定的,然后,对于每一种方向内部顺序不用考虑,然后排列组合就完事了
对称性上又出错了,哎,自己也没找个小数据试一下,就...(a,b)和(a,a-b+1)是对称的

HEX SDUT 3896 17年山东省赛D题_#defineHEX SDUT 3896 17年山东省赛D题_ios_02
#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cmath>
#include<ctime>
#include<set>
#include<map>
#include<stack>
#include<cstring>
#define inf 2147483647
#define ls rt<<1
#define rs rt<<1|1
#define lson ls,nl,mid,l,r
#define rson rs,mid+1,nr,l,r
#define N 100010
#define For(i,a,b) for(long long i=a;i<=b;i++)
#define p(a) putchar(a)
#define g() getchar()

using namespace std;
long long l,r,x,y,d;
long long a[100010],inv[100010];
long long p=1000000007;
long long ans;
long long down;

void in(long long &x){
    long long y=1;
    char c=g();x=0;
    while(c<'0'||c>'9'){
        if(c=='-')y=-1;
        c=g();
    }
    while(c<='9'&&c>='0'){
        x=(x<<1)+(x<<3)+c-'0';c=g();
    }
    x*=y;
}
void o(long long x){
    if(x<0){
        p('-');
        x=-x;
    }
    if(x>9)o(x/10);
    p(x%10+'0');
}

long long ksm(long long a,long long b,long long p){
    while(b%2==0){
        a*=a;
        a%=p;
        b>>=1;
    }
    long long r=1;
    while(b>0){
        if(b%2==1){
            r*=a;
            r%=p;
        }
        a*=a;
        a%=p;
        b>>=1;
    }
    return r;
}

void clear(){
    ans=0;
    down=0;
}

int main(){
    a[0]=1;
    For(i,1,100000)
        a[i]=(a[i-1]*i)%p;
    For(i,0,100000)
        inv[i]=ksm(a[i],p-2,p)%p;
    while(cin>>x>>y){
        clear();
        y=max(y,x-y+1);
        l=x-y;
        r=y-1;
        while(l>=0&&r>=0){
            ans+=a[l+r+down]*inv[l]%p*inv[r]%p*inv[down]%p;
            ans%=p;
            l--;
            r--;
            down++;
        }
        o(ans);p('\n');
    }
    return 0;
}
View Code