3 条题解
-
1
世界上最好的题解😄 解析都在代码里呦😊
#include<bits/stdc++.h> using namespace std; int t,k,n,m,a[2100][2100],sum[2100][2100]; //t次查询 给定k求k的倍数 n个数字中 找m个数字组合 组合数数组 二位前缀和 int main(){ cin>>t>>k; for(int i=1;i<=2000;i++){//预处理杨辉三角 a[i][0]=a[i][i]=1;//组合数a(n,0)=a(n,n)=1 /* 递归生成其它组合数 因为是求组合数a(A,B),那么A一定要大于等于B,否则就不对了 所以,j的循环范围最大就只能是i了 */ for(int j=1;j<i;j++)a[i][j]=(a[i-1][j]+a[i-1][j-1])%k; /* for循环:因为一头一尾j→0和i都被设置成了1,所以循环的范围就是中间剩下的了 a[i][j]=(a[i-1][j]+a[i-1][j-1])%k: 因为a数组中已经有了的数据都是被模上k后存入的, 所以这里做加法前就不用再模了,再模也是那么回事,反而速度更慢了 */ } for(int i=1;i<=2000;i++)//标准的二位前缀和 for(int j=1;j<=2000;j++){ int x=0; if(i>=j)x=(a[i][j]==0); sum[i][j]=sum[i-1][j]+sum[i][j-1]+x-sum[i-1][j-1]; } while(t--){//进行输出 cin>>n>>m; cout<<sum[n][m]<<endl; } return 0; }
看完麻烦各位大佬点个赞哟😝
-
0
inline void build() { c[0][0]=1; c[1][0]=c[1][1]=1; for(int i=2;i<=2000;i++) { c[i][0]=1; for(int j=1;j<=i;j++) { c[i][j]=(c[i-1][j-1]+c[i-1][j])%k; ans[i][j]=ans[i-1][j]+ans[i][j-1]-ans[i-1][j-1];//前缀和。 if(!c[i][j])ans[i][j]++;//如果满足结论,计数加一。(有没有感觉很像我的玄学优化) } ans[i][i+1]=ans[i][i];//继承。 } } inline void solve() { t=read(),k=read(); build(); while(t--) { n=read(),m=read(); if(m>n)printf("%lld\n",ans[n][n]);//如果m>n,ans只会达到n,只需输出ans[n,n]就可以了。 else printf("%lld\n",ans[n][m]); } }
-
-1
#include <iostream> using namespace std; int t,k,n,m, c[2010][2010],s[2010][2100]; int main(){ cin >> t >> k; c[1][1] = 1; for(int i = 0; i <= 2000; i++) c[i][0] = 1; for(int i = 2; i <= 2000; i++) for(int j = 1; j <= i; j++) c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % k; for(int i = 2;i <= 2000;i++){ for(int j = 1;j <= i;j++){ s[i][j] = s[i - 1][j] + s[i][j -1]-s[i-1][j-1]; if(c[i][j]==0) s[i][j]+=1; } s[i][i+1]=s[i][i]; } while(t--){ cin>>n>>m; if(m > n) m=n; cout<<s[n][m]<<endl; } return 0; }
- 1
信息
- ID
- 1765
- 时间
- 1000ms
- 内存
- 500MiB
- 难度
- 4
- 标签
- 递交数
- 19
- 已通过
- 8
- 上传者