dcx游走 - 组合计数

题目大意:平面直角坐标系开始在(0,0)每次可以向上下左右走一个单位距离。1e6次询问从原点走k步到(a,b)的方案数。k,a,b<=1e6。
题解:将坐标变换为(x+y,x-y)这样移动方案变为(±1,±1),从而横纵坐标独立,然后O(1)出解。

#include<bits/stdc++.h>
#define gc getchar()
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define Rep(i,v) rep(i,0,(int)v.size()-1)
#define lint long long
#define mod 998244353
#define N 3000010
#define db long double
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
typedef pair<int,int> pii;
typedef set<int>::iterator sit;
int fac[N],facinv[N];
inline int fast_pow(int x,int k,int ans=1) { for(;k;k>>=1,x=(lint)x*x%mod) (k&1)?ans=(lint)ans*x%mod:0;return ans; }
inline int prelude(int n)
{
    rep(i,fac[0]=1,n) fac[i]=(lint)fac[i-1]*i%mod;
    facinv[n]=fast_pow(fac[n],mod-2);
    for(int i=n-1;i>=0;i--)
        facinv[i]=facinv[i+1]*(i+1ll)%mod;
    return 0;
}
inline int C(int n,int m) { return (lint)fac[n]*facinv[m]%mod*facinv[n-m]%mod; }
#ifdef ONLINE_JUDGE
namespace IO { const int S=(1<<20)+5;char buf[S],*H,*T;inline char getc() { if(H==T) T=(H=buf)+fread(buf,1,S,stdin);if(H==T) return -1;return *H++; }
    inline int inn() { int x=0,c=getc();while(!isdigit(c)) c=getc();while(isdigit(c)) x=(((x<<2)+x)<<1)+(c^'0'),c=getc();return x; } }using namespace IO;
#else
inline int inn() { int x,ch;while((ch=gc)<'0'||ch>'9');x=ch^'0';while((ch=gc)>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^'0');return x; }
#endif
char ss[20000000],tt[20];int ssl,ttl;
inline int show(int x)
{
    if(!x) ss[++ssl]='0';
    for(ttl=0;x;x/=10) tt[++ttl]=char(x%10+'0');
    for(;ttl;ttl--) ss[++ssl]=tt[ttl];
    return ss[++ssl]='\n';
}
int main()
{
    prelude(N-1);
    for(int T=inn(),Tis1=(T==1);T;T--)
    {
        int a=inn(),b=inn(),k=inn();
        if(a+b>k||(a+b)%2!=k%2) { show(0);continue; }
        show(int((lint)C(k,(a+b+k)/2)*C(k,(k-a+b)/2)%mod));
    }
    return fwrite(ss+1,sizeof(char),ssl,stdout),0;
}

猜你喜欢

转载自blog.csdn.net/Mys_C_K/article/details/83586241