Ural 1903 Unidentified Ships 组合数 + 乘法逆元
一開始题意没读懂。英语是硬伤,事实上是这道题目真的有点饶人,后来补题,看懂了意思。从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;
}
浙公网安备 33010602011771号