洛谷P2822组合数问题(预处理+取模优化)
洛谷P2822组合数问题(预处理+取模优化)
题目:
给定n,m求
\(\tbinom{i}{j}\%k == 0 的个数(其中i<=n,j<=m)\)
一共t个样例
t为 1e4 的数据,n,m分别为2000
思路:
这题杨辉三角打表预处理(开始和凯宝想的是其他公式打表...现在感觉好憨憨)。但是处理完仍然过不了,会WA,因为会溢出。所以需要取模,但是菜鸡不知道怎么取。看了题解之后知道了,可以这样玩:
\(\tbinom{i}{j}\%k =(\tbinom{i-1}{j-1}\%k+\tbinom{i-1}{j}\%k)\%k\)
就是提前取模,确实orzing
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<ll,ll>
const int mod = 1e9+7;
const int N = 2000+500;
ll fac[N][N],ans[N][N];
/*
杨辉三角和记录这一行有多少个合法数据(其他题解里写的是所有的最后用前缀和的方式求解)
*/
void init(int k){
fac[0][0] = 1;
fac[1][0] = fac[1][1] = 1;
for(int i = 2;i <= 2000;i++){
fac[i][0] = 1;
for(int j = 1;j <= i;j++){
fac[i][j] = (fac[i-1][j-1]+fac[i-1][j])%k;//这样就可以了
if(j == 0) ans[i][j] = 0;
else ans[i][j] = ans[i][j-1]+(fac[i][j] == 0) ;//懒狗写法
}
}
}
int main() {
ios::sync_with_stdio(false);
ll t,k;
cin>>t>>k;
init(k);
while(t--){
ll n,m;
cin>>n>>m;
ll tot = 0;
for(ll i = 1;i <= n;i++){
ll in = min(i,m);
tot += ans[i][in];
}
cout<<tot<<endl;
}
return 0;
}