[BZOJ 3260] 跳
阿新 • • 發佈:2017-10-15
return for -s define sigma script space scanf mod
現在,邪教想知道從 (0,0)出發到(N,M),最少花費多少體力(到達 (0,0) 點花費的
體力也需要被算入)。
由於答案可能很大,只需要輸出答案對 10^9+7取模的結果。
1 2
Description
邪教喜歡在各種各樣空間內跳。 現在,邪教來到了一個二維平面。在這個平面內,如果邪教當前跳到了 (x,y) , 那麽他下一步可以選擇跳到以下 4個點: (x-1,y), (x+1,y), (x,y-1), (x,y+1)。 而每當邪教到達一個點,他需要耗費一些體力,假設到達 (x,y)需要耗費的體 力用 C(x,y)表示。 對於 C(x,y),有以下幾個性質: 1 、若x=0或者 y=0,則 C(x,y)=1。 2 、若x>0且 y>0,則 C(x,y)=C(x,y-1)+C(x-1,y)。 3 、若x<0且 y<0,則 C(x,y)=無窮大。Input
讀入兩個整數 N ,M,表示邪教想到達的點。Output
輸出僅一個整數,表示邪教需要花費的最小體力對 10^9+7取模的結果。Sample Input
1 2
Sample Output
6HINT
對於 100% 的數據,滿足 0<=N, M<=10^12 ,N*M<=10^12。
題解:Lucas定理+貪心
先打出個表來,發現c數組就是楊輝三角嘛(只不過45°的放在數組裏。
然後(x,y)的C值,就是組合數C(x+y,y)。
那麽對於點n,m,先沿著(0,0)-->(1,0)-->(2.0)--...-->(n,0)
然後(n,1)-->(n,2)-->(n,3)--...(n,m),表上看出C(n,m)=C(m,n),(這個C是價值
然後用Lucas求組合數就可以啦。
其實本來想做費馬小定理來著...
在Lucas求逆元中,n!/(m!*(n-m)!)==> n!*(m!*(n-m)在mod數意義下的逆元)
由歐拉定理知道a^(phi(n))≡1(mod n)當a,n互質時,費馬小定理為當n為質數時
a^(phi(n))=a^(n-1)≡1(mod n),那麽a關於MOD n意義下的逆元就是a^(n-2)。
假設n>m(讓豎著走的1多一點
那麽答案就是n+sigma(i=0--m)C(n+i,i)
sigma那個是 C(n+m+1,m)。
這個我不會證.....才怪 略略略
證明:C(n,0)+C(n+1,1)+C(n+2,2)+C(n+2,3)+....+C(n+m,m)
額...不會 推薦播客
代碼:
最近Lucas定理做的太多了...不做了.... 感覺這個題的數據範圍有點玄....
#include<iostream> #include<cstdio> #include<cstring> #define LL long long using namespace std; const LL mod=1e9+7; LL m,n; LL ksm(LL x,LL y){ LL ret=1; while(y){ if(y&1)ret=ret*x%mod; x=x*x%mod; y>>=1; } return ret; } LL C(LL n,LL m){ if(m>n)return 0; LL s1=1,s2=1; for(LL i=n-m+1;i<=n;i++)s1=s1*i%mod; for(LL i=1;i<=m;i++)s2=s2*i%mod; return s1*ksm(s2,mod-2); } LL Lucas(LL n,LL m){ if(!m)return 1; return C(n%mod,m%mod)*Lucas(n/mod,m/mod)%mod; } int main(){ scanf("%lld%lld",&n,&m); printf("%lld\n",(max(n,m)%mod+Lucas(n+m+1,min(n,m))%mod)%mod); return 0; }
[BZOJ 3260] 跳