T50759 吃豆子

ddd出的noip+模拟赛的T1

好难啊!

我的思路是用过河卒那样的加法原理算出1000*1000之内的两个点之间的距离,然后一个一个豆子来吃,吃到终点,方案数就乘法原理一个一个乘。

但是很不幸,评测的时候五颜六色,只有45pts。


正解是这样的:

你把人的坐标设为\((x,y)\),因为人只能往右或者下走,所以要不x来加1,要不y来加1。不管怎样他们的和都会+1。

所以我们搞个结构体,根据他们的坐标和从小到大排序。

然后就能一个点到一个点之间来算方案数。

这个方案数是多少呢?

\(dx=x_i-x_{i-1},dy=y_i-y_{i-1}\),则局部方案数是\(C_{dx+dy}^{dx}\)\(C_{dx+dy}^{dy}\)

组合数就按照预处理阶乘,求逆元等步骤可以很快地单一搞出来。

所以这些东西相乘就是答案。


有个坑点:这些东西相乘的时候可能会在你没留意的时候爆int,所以还是long long保平安。昨晚因为这个调得我心态有点爆炸。

代码:

#include<cstdio>
#include<algorithm>

#define ll long long
const ll maxn = 300005;
const ll mod = 1e9 + 7;
struct Nodes
{
    ll x, y;
} s[maxn];

ll frac[maxn];

ll n, m, k;
bool cmp(Nodes a, Nodes b)
{
    return a.x + a.y < b.x + b.y;
}

ll exgcd(ll a, ll b, ll &x, ll &y)
{
    if(b == 0){ x = 1; y = 0; return a; }
    else
    {
        ll ret = exgcd(b, a % b, x, y);
        ll t = x;
        x = y;
        y = t - a / b * y;
        return ret;
    }
}
ll inv(ll a)
{
    // a * inv === 1 (mod p)
    // a * inv - y * p = 1
    
    ll x, y;
    exgcd(a, mod, x, y);
    return (x % mod + mod) % mod;
}
ll read()
{
    ll ans = 0, s = 1;
    char ch = getchar();
    while(ch > '9' || ch < '0'){ if(ch == '-') s = -1; ch = getchar(); }
    while(ch >= '0' && ch <= '9') ans = (ans << 3) + (ans << 1) + ch - '0', ch = getchar();
    return s * ans;
}
void init()
{
    frac[0] = 1;
    for(int i = 1; i <= 300000; i++) frac[i] = frac[i - 1] * i % mod;
}
ll C(ll m, ll n)
{
    return frac[m] * inv(frac[n]) % mod * inv(frac[m - n]) % mod;
}
int main()
{
    n = read(), m = read(), k = read();
    s[1] = (Nodes){1, 1};
    for(int i = 2; i <= k + 1; i++)
    {
        s[i].x = read(), s[i].y = read();
    }
    s[k + 2] = (Nodes){n, m};
    k += 2;
    std::sort(s + 1, s + k + 1, cmp);
    ll ans = 1;
    
    init();
    for(int i = 2; i <= k; i++)
    {
        ll dx = s[i].x - s[i - 1].x;
        ll dy = s[i].y - s[i - 1].y;
        
        if(dx < 0 || dy < 0)
        {
            printf("0\n");
            return 0;
        }
        
        //printf("%d %d\n", dx, dy);
        ans = ans * C(dx + dy, dx) % mod;
        
    }
    printf("%lld\n", ans);
    return 0;
    
}

猜你喜欢

转载自www.cnblogs.com/Garen-Wang/p/9813494.html