Luogu 2822 组合数问题
题目链接:https://www.luogu.org/problemnew/show/P2822
思路:
考虑复杂度,发现暴力不可拿全分。
因为求的是一个范围内满足条件的总个数,所以我们在处理组合数之时就可以判断是否满足条件,然后使用二维前缀和计算,来使查询复杂度为$O(1)$。
最后总查询复杂度为$O(T*n)$。
代码:
#include <cstdio> #include <cctype> #include <cstring> #include <iostream> const int MAXN=2050; using namespace std; int n,m,t,k,ans,last,c[MAXN][MAXN],p[MAXN][MAXN]; int get_min(int x,int y){ return x<y?x:y; } int main(){ cin>>t>>k; for(int i=0;i<=2001;i++) c[i][0]=1; for(int i=1;i<=2001;i++){ for(int j=1;j<=i;j++){ c[i][j]=(c[i-1][j]+c[i-1][j-1])%k; } } for(int i=0;i<=2001;i++){ for(int j=0;j<=2001;j++){ p[i][j]=c[i][j]?0:1; p[i][j]+=p[i-1][j]+p[i][j-1]-p[i-1][j-1]; } } while(t--){ cin>>n>>m; for(int i=0;i<=n;i++) ans+=p[i][get_min(i,m)]-p[i-1][get_min(i,m)]; cout<<ans<<endl; last=ans=0; } return 0; }