牛客补题:链接:登录—专业IT笔试面试备考平台_牛客网
我有精兵组阵,兵阵可看做一个 n×m 的矩阵,现在从左上角 (1,1) 派遣出通讯兵 去 (n,m) 传令,通讯兵每一步仅能向右走或者向下走,求会有几种不同的路线,答案对 998244353 取模。
n<= 1000000,m,T <= 5000
这道题很经典啊,寒假集训学的dp,奈何当时看了数据范围,dp肯定爆。
正确题解是数学组合数,要走到(n,m)坐标中,右走m步,下走n步。而不同的路径可以看作是从n+m步中选择n步向右走的方案数,即为组合数C(n+m, n)。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int Mod=998244353;
const int N=2e6;
vector<int>g(N,0);
int ksm(int a,int b){//a^b
int ans=1;
while(b){
if(b&1) ans=ans*a%Mod;
a=a*a%Mod;
b>>=1;
}
return ans;
}
int C(int x,int y){//组合数:x中取y
if(x==0||y==0) return 1;
return g[x]*ksm((g[x-y]*g[y])%Mod,Mod-2)%Mod;//费马小定理求逆元
}//(g[x-y]*g[y])%Mod 这里不取Mod,精度会WA
void solve(){
int n,m;
cin>>n>>m;
n--,m--;
cout<<C(n+m,m)<<'\n';
}
signed main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
g[0]=1;
for(int i=1;i<=N;i++){//预处理阶乘
g[i]=(g[i-1]*i)%Mod;
}
int t;
cin>>t;
while(t--){
solve();
}
return 0;
}
预处理阶乘。组合数公式:C(y,x)=!x / !y*!(x-y)
除数取模,得用逆元啊!费马小定理求逆元,转换为乘法,用快速幂。时间复杂度转为O(nlogn)级别。
细节:在传入快速幂,(g[x-y]*g[y])%Mod 这里不取Mod,精度会WA。
总结:思路最重要,就是组合数求方案,不管是再高深的算法,快速幂,逆元,都是用来实现你思路的工具罢了。学思路!!!
2266

被折叠的 条评论
为什么被折叠?



