Ural 1903 Unidentified Ships 組合數 + 乘法逆元
阿新 • • 發佈:2017-05-29
乘法逆元 內存 i++ targe dsm def ble pan bsp
一開始題意沒讀懂。英語是硬傷,事實上是這道題目真的有點饒人,後來補題,看懂了意思。從n個數中挑出t個,然後第k個必需要在,挑出的t個數要排序成不下降的順序,然後 原本那個第k個數在這個跳出的t個數其中要在第x的位置
分析:直接找出比第k個數小的數的個數,還有比第k個數大的數的個數,當然啦還有可能存在與第k個數相等的數的個數,唉呀,一開始漏了相等的情況,沒看題目案例,真是作死啊,後來全弄好了。那不就是在比它小的裏面挑x-1個數字。當然也能夠從相等的裏面挑了補。然後在比它大的 裏面挑t-x個數 當然也能夠從相等的裏面挑了補。然後就是理清楚關系就好了,每一次三個部分關系弄清楚 相乘 然後求總和。 一開始直接套了模版 大概須要開[5000][5000]的數組最起碼,但是超了內存,沒辦法 事實上C(5,4) == C(5,1)通過這個我們事實上僅僅須要構造二維一半就可以那就是[5000][2500]的空間就夠了,這樣寫一個就可以,但是寫了半天沒寫好。由於腦殘了 忘了 c(5,0)的值為1。最後看了別人的構造才醒悟過來。真是腦殘,當然除了這種方法 我們還能夠使用直接求組合數的函數 的方法,由於這道題目要取模。而直接求組合數是涉及了除法的,除法對取模有影響,所以應該要轉化為乘法,那就是求乘法逆元咯,
凝視部分 是直接遞推構造組合數的部分
題目:http://acm.timus.ru/problem.aspx?space=1&num=1903
#include<iostream> #include<cstdio> #include<list> #include<algorithm> #include<cstring> #include<string> #include<queue> #include<stack> #include<map> #include<vector> #include<cmath> #include<memory.h> #include<set> #define ll long long #define LL __int64 #define eps 1e-8 const int inf = 0xfffffff; const ll INF = 1ll<<61; using namespace std; //vector<pair<int,int> > G; //typedef pair<int,int > P; //vector<pair<int,int> > ::iterator iter; // //map<ll,int >mp; //map<ll,int >::iterator p; const int MOD = 1000000007; int t,n,k,x; int num[5000 + 5]; int c[5000 + 5][2500 + 5]; //void C() { // for(int i=0; i<=5000; ++i) { // c[i][0] = 1; // } // c[1][1] = 1; // for(int i=2; i<=5000; ++i) // for(int j=1; j<=i/2; ++j) // c[i][j] = (c[i-1][min(j - 1,i - j)] + c[i-1][min(j,i - j - 1)]) % MOD; //} ll exgcd(ll a, ll b, ll &x, ll &y) { if(!b) { x = 1; y = 0; return a; } ll r = exgcd(b, a%b, y, x); y -= a/b*x; return r; } ll inv(ll a, ll m) { ll x,y,gcd = exgcd(a, m, x, y); if(x < 0) x += m; return x; } ll C(ll n,ll m)//計算組合數C(n,m) { ll t1=1,t2=1; for(LL i=n;i>m;i--) { t1=(t1*i)%MOD; t2=(t2*(i-m))%MOD; } return t1*inv(t2,MOD)%MOD; } int main() { /*C();*/ while(scanf("%d %d",&n,&t) == 2) { for(int i=1;i<=n;i++) scanf("%d",&num[i]); scanf("%d %d",&k,&x); int lit = 0,big = 0,equ = 0; for(int i=1;i<=n;i++) { if(num[i] < num[k]) lit++; else if(num[i] == num[k]) equ++; else big++; } equ--; ll ans = 0ll; int left = x - 1; int right = t - x; for(int i=0;i<=min(lit,left);i++) { for(int j=0;j<=min(right,big);j++) { int k = t - i - j - 1; if(k < 0)break; if(k > equ)continue; if(i + k + 1< x)break; ll tmp = 1; /*int tx = c[lit][min(i,lit - i)]; int ty = c[big][min(j,big - j)]; tmp = tmp * c[lit][min(i,lit - i)] * c[big][min(j,big - j)] %MOD; int tz = c[equ][min(k,equ - k)]; tmp = tmp * c[equ][min(k,equ - k)]%MOD;*/ tmp = tmp * C(lit,min(i,lit - i)) * C(big,min(j,big - j)) %MOD; tmp = tmp * C(equ,min(k,equ - k))%MOD; ans += tmp; ans %= MOD; } } printf("%I64d\n",ans); } return 0; }
Ural 1903 Unidentified Ships 組合數 + 乘法逆元