洛谷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;
}

posted @ 2021-05-12 21:10  Paranoid5  阅读(140)  评论(0编辑  收藏  举报