刷水有益健康->实际上除了增长信心外,,没什么作用了,, 这道题 感谢 LZH dalao,嗯,总之是生命中比较重要的一个人吧。。。扯远了
看到数据的那一刻,不想到 算法都不容易 -> 递推 杨辉三角 (LZH dalao 告诉本蒟蒻的 : 一脉相承,很简单的)
不过因为多组数据,所以 了,我们可以明显的发现 是固定的,所以,整个 好了 , 表示 中 满足 取模条件的 个数 ,然后 就可以查询了
然鹅,这样只有 分,因为即使是 也会溢出,于是 要在 递推时 就取模,并将 中的条件 加成 (原来是 取模后等于零)
虽然说,里面涉及 容斥 ,然鹅,容斥 很简单,很好想。。。
递推 杨辉三角 :-> 当然是预处理了:)
Cnm[i][j]=( Cnm[i-1][j-1]+Cnm[i-1][j] ) % (LL)k;
: 容斥(一个 好听 的名字)
dp[i][j]=dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1];
细节:
dp[i][i+1]=dp[i][i];
【 附上 AC 代码 】
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define LL long long
using namespace std;
inline int wread(){
char c(getchar ());int wans(0),flag(1);
while (c<'0' || c>'9'){if (c=='-') flag=-1; c=getchar();}
while (c>='0' && c<='9'){wans=wans*10+c-'0';c=getchar();}
return wans*=flag;
}
LL Cnm[2003][2003];
LL dp[2003][2003];
int main (){
int t(wread()), k(wread());
for (int i(0);i<=2000;++i){
if (i==0) {Cnm[0][0]=1;continue;}
for (int j(0);j<=i;++j){
if (j==0) {Cnm[i][0]=1; continue;}
Cnm[i][j]=( Cnm[i-1][j-1]+Cnm[i-1][j] ) % (LL)k;
}
}
for (int i(1);i<=2000;++i){
for (int j(1);j<=i;++j){
dp[i][j]=dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1];
if (Cnm[i][j]==0) dp[i][j]++;
}
dp[i][i+1]=dp[i][i];
}
while (t--){
int i(wread()),j(wread());
printf("%lld\n",dp[i][min(j,i)]);
}
return 0;
}
扫描二维码关注公众号,回复:
2571835 查看本文章