zoukankan      html  css  js  c++  java
  • 神秘题目

    Description

    在一个平面直角坐标系中,你站在原点,即(0,0)上。你每次可以选择往上下左右中的一个方向走1个单位的距离(不能不走)。问你用k步走到(a,b)的方案数。(只需要k步后在终点即可,不关注途中是否经过终点)

    Input

    本题有多组数据。

    第一行一个整数t,表示数据组数。

    接下来t行,第i+1行包含三个整数ai,bi,ki,表示第i次询问终点为(ai,bi),步数为ki

    Output

    共t行,每行一个整数,表示答案。

    Sample Input

    3

    1 1 1

    0 1 2

    4 4 10

    Sample Output

    0

    0

    2520

    HINT

    对于100%的数据,1<t≤106,0≤ai,bi≤106,0≤ki≤3*106


    Solution

    (本题解仅适用于我这种只会暴力推导的蒟蒻选手,请开题就旋转45°秒题的大佬们出门左转慢走不送。)

    显然,当a+b<k或k-a-b为奇数时,没有符合要求的方案。

    从(0,0)到(a,b)至少需要a+b步。

    对于剩下的k-a-b步,需满足向左(上)走和向右(下)走的步数相等。

    令n=(k-a-b)/2,我们可以得到

    $ans=sumlimits_{i=0}^{n}({{k}atop{a+2i}})({{a+2i}atop{i}})({{b+2n-2i}atop{n-i}})$

    $=sumlimits_{i=0}^{n}frac{k!}{i!(a+i)!(n-i)!(b+n-i)!}$(注:k-a-2i=a+b+2n-a-2i=b+2n-2i)

    接下来是最重要的一步,我们可以发现i+(n-i)=n,(a+i)+(b+n-i)=k-n,n+(k-n)=k,于是我们可以考虑搞一点事情↓

    $k!=frac{k!*n!*(n-k)!}{n!*(n-k)!}$

    代入原式可得

    $ans=({{k}atop{n}})sumlimits_{i=0}^{n}({{n}atop{i}})({{k-n}atop{a+i}})$

    似乎看不出什么,我们将$({{k-n}atop{a+i}})$变为$({{k-n}atop{k-n-a-i}})$。

    理性分析一下我们可以发现,$sumlimits_{i=0}^{n}({{n}atop{i}})({{k-n}atop{k-n-a-i}})$表示的是从k个球中取k-n-a个球的方案数,则$ans=({{k}atop{n}})({{k}atop{k-n-a}})$,单次询问的时间复杂度O(1),总时间复杂度为O(t)。

    Code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int mod=998244353;
    const int len=25000000;
    char s[len];int pos=0;
    inline int rd(){
        char c=s[pos++];int flag=1,x=0;
        for(;c<'0'||c>'9';c=s[pos++])if(c=='-')flag=-1;
        for(;c>='0'&&c<='9';c=s[pos++])x=x*10+c-'0';
        return x*flag;
    }
    int fac[3000010]={1},inv[3000010]={1};
    int power(int x,int k){
        int res=1,s=x;
        for(;k;k>>=1){
            if(k&1)
                res=(ll)res*s%mod;
            s=(ll)s*s%mod;
        }
        return res;
    }
    void prepare(){
        for(int i=1;i<=3000000;i++)
            fac[i]=(ll)fac[i-1]*i%mod;
        inv[3000000]=power(fac[3000000],mod-2);
        for(int i=2999999;i;i--)
            inv[i]=(ll)inv[i+1]*(i+1)%mod;
        return;
    }
    int C(int n,int m){
        return (ll)fac[n]*inv[m]%mod*inv[n-m]%mod;
    }
    int solve(int a,int b,int k){
        int n=(k-a-b)>>1;
        return (ll)C(k,n)*C(k,k-n-a)%mod;
    }
    int main(){
        freopen("data_A.in","r",stdin);
        freopen("ans_A.out","w",stdout);
        fread(s,1,len,stdin);
        prepare();
        for(int t=rd();t--;){
            int a=rd(),b=rd(),k=rd();
            if(a+b>k||((k-a-b)&1)){
                puts("0");
                continue;
            }
            printf("%d
    ",solve(a,b,k));
        }
        return 0;
    }
  • 相关阅读:
    当jsp页面完全加载完成后执行一个js函数
    Spring Framework 下载地址_现在可用
    学习Linux shell脚本之前的基础知识
    如何在Oracle中复制表结构和表数据
    内存溢出的问题
    全面屏底部小横条设置不显示
    Android 4.4系统,User模式adb默认开启,取消授权,开启root调试记录
    Android Native Binder,在Native层与App交互数据
    Android Jni开发,报com.android.ide.common.process.ProcessException: Error configuring 错误解决方案
    Android DataBinding不能自动生成ViewDataBinding类的解决方法
  • 原文地址:https://www.cnblogs.com/gzez181027/p/9884213.html
Copyright © 2011-2022 走看看