3 条题解

  • 1
    @ 2024-5-4 16:40:18

    世界上最好的题解😄 解析都在代码里呦😊

    #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
      @ 2022-8-21 22:17:55
      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
        @ 2022-8-3 16:12:02
        #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
        上传者