HEX SDUT 3896 17年山东省赛D题
HEX SDUT 3896 17年山东省赛D题
这个题是从矩形的左下角走到右上角的方案数的变形题,看来我对以前做过的题理解还不是太深,或者是忘了。对于这种题目,直接分析它的性质就完事了。从(1,1)走到(a,b)向左走的步数和向右走的步数是确定的,向下是代表向左向右各走了一步。细节:利用对称性,线性推逆元
对于每一种情况,向左下、向右下、向下的次数都是确定的,然后,对于每一种方向内部顺序不用考虑,然后排列组合就完事了
对称性上又出错了,哎,自己也没找个小数据试一下,就...(a,b)和(a,a-b+1)是对称的
#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; }