2 条题解

  • 0
    @ 2025-10-8 16:54:04
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL; 
    LL f[230][12],ff[230][230][12];
    //f[i][j]表示i个球放入j个相同盒子的方案数(允许盒子的球数为0)
    //f[x][i][j]表示数字i分成j份有几种分法,且第一个盒子放x个球(允许盒子的球数为0)
    int main()
    {
        int n,m;LL k;scanf("%d%d%lld",&n,&m,&k);n-=m;//提前给每个盒子放入1个球 
        memset(f,0,sizeof f);
        for(int i=0;i<=n;i++) f[i][1]=1;//i个球放入1个盒子,只有1种方案 
        for(int j=1;j<=m;j++) f[0][j]=1;//0个球放入j个盒子,只有1种方案 
        for(int i=1;i<=n;i++)
            for(int j=2;j<=m;j++)
            {
            	for(int k=0;k<=i/j;k++)
    				f[i][j]+=f[i-k*j][j-1]; //i个球放入j个盒子,第1个盒子放k个(后面每个盒子都放k个) 
    		}
    	memset(ff,0,sizeof ff);
    	for(int i=0;i<=n;i++) ff[i][i][1]=1;
    	for(int j=1;j<=m;j++) ff[0][0][j]=1;
    	for(int i=1;i<=n;i++)
    		for(int j=2;j<=m;j++)
    			for(int x=0;x<=i/j;x++)//把i分成j份是x的上限 
    				ff[x][i][j]=f[i-x*j][j-1]; 
    	 
    	int xx=1;//xx表示之前提前放入当前至后面的每个盒子的球个数 
    	for(int i=1;i<m;i++)//逐个确定每个盒子放的球数 
    	{
    		int x=0;
    		while(k>ff[x][n][m-i+1])
    		{
    			k-=ff[x][n][m-i+1];
    			x++;
    		}
    		printf("%d ",x+xx);
    		n=n-x*(m-i+1);
    		xx+=x;//第i至m个盒子,每个盒子加入x个 
    	}
    	printf("%d\n",n+xx);
        return 0; 
    }
    
    /*
    f[i][j]表示数字i分成j份有几种分法(i个球放进j个盒子) 
    f[x][i][j]表示数字i分成j份有几种分法,且第一个盒子放x个球
    */
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL; 
    LL f[230][12],ff[230][230][12];
    int main()
    {
        int n,m;LL k;scanf("%d%d%lld",&n,&m,&k);
        memset(f,0,sizeof f);
        for(int i=1;i<=n;i++) f[i][1]=1;
        for(int i=1;i<=n;i++)
            for(int j=2;j<=m && j<=i;j++)
            {
            	f[i][j]=f[i-1][j-1]+f[i-j][j]; 
    		}
    	memset(ff,0,sizeof ff);
    	for(int i=1;i<=n;i++) ff[i][i][1]=1;
    	for(int i=1;i<=n;i++)
    		for(int j=2;j<=m && j<=i;j++)
    			for(int x=1;x<=i/j;x++)
    				ff[x][i][j]=f[i-x-(x-1)*(j-1)][j-1];//i-x-(x-1)*(j-1)的意思:第一个盒子放x个,并且后面每个盒子提前放x-1个 
    	 
    	int xx=0;//xx表示之前提前放入的球的个数和 
    	for(int i=1;i<m;i++)//逐个确定每个盒子放的球数 
    	{
    		int x=1;
    		while(k>ff[x][n][m-i+1])
    		{
    			k-=ff[x][n][m-i+1];
    			x++;
    		}
    		printf("%d ",x+xx);
    		xx+=x-1;
    		n=n-(x +  (x-1)*(m-i) );//第i个盒子加入x个,并且后面每个盒子提前加x-1个 
    	}
    	printf("%d\n",n+xx);
        return 0; 
    }
    
    • 0
      @ 2025-10-8 16:53:47


      #include<bits/stdc++.h>
      using namespace std;
      typedef long long LL; 
      LL f[230][12],ff[230][230][12];
      //f[i][j]表示i个球放入j个相同盒子的方案数(允许盒子的球数为0)
      //f[x][i][j]表示数字i分成j份有几种分法,且第一个盒子放x个球(允许盒子的球数为0)
      int main()
      {
          int n,m;LL k;scanf("%d%d%lld",&n,&m,&k);n-=m;//提前给每个盒子放入1个球 
          memset(f,0,sizeof f);
          for(int i=0;i<=n;i++) f[i][1]=1;//i个球放入1个盒子,只有1种方案 
          for(int j=1;j<=m;j++) f[0][j]=1;//0个球放入j个盒子,只有1种方案 
          for(int i=1;i<=n;i++)
              for(int j=2;j<=m;j++)
              {
              	for(int k=0;k<=i/j;k++)
      				f[i][j]+=f[i-k*j][j-1]; //i个球放入j个盒子,第1个盒子放k个(后面每个盒子都放k个) 
      		}
      	memset(ff,0,sizeof ff);
      	for(int i=0;i<=n;i++) ff[i][i][1]=1;
      	for(int j=1;j<=m;j++) ff[0][0][j]=1;
      	for(int i=1;i<=n;i++)
      		for(int j=2;j<=m;j++)
      			for(int x=0;x<=i/j;x++)//把i分成j份是x的上限 
      				ff[x][i][j]=f[i-x*j][j-1]; 
      
      int xx=1;//xx表示之前提前放入当前至后面的每个盒子的球个数 
      for(int i=1;i&lt;m;i++)//逐个确定每个盒子放的球数 
      {
      	int x=0;
      	while(k&gt;ff[x][n][m-i+1])
      	{
      		k-=ff[x][n][m-i+1];
      		x++;
      	}
      	printf("%d "&#44;x+xx);
      	n=n-x*(m-i+1);
      	xx+=x;//第i至m个盒子,每个盒子加入x个 
      }
      printf("%d\n"&#44;n+xx);
      return 0; 
      

      }

      </p>






      /*
      f[i][j]表示数字i分成j份有几种分法(i个球放进j个盒子) 
      f[x][i][j]表示数字i分成j份有几种分法,且第一个盒子放x个球
      */
      #include<bits/stdc++.h>
      using namespace std;
      typedef long long LL; 
      LL f[230][12],ff[230][230][12];
      int main()
      {
          int n,m;LL k;scanf("%d%d%lld",&n,&m,&k);
          memset(f,0,sizeof f);
          for(int i=1;i<=n;i++) f[i][1]=1;
          for(int i=1;i<=n;i++)
              for(int j=2;j<=m && j<=i;j++)
              {
              	f[i][j]=f[i-1][j-1]+f[i-j][j]; 
      		}
      	memset(ff,0,sizeof ff);
      	for(int i=1;i<=n;i++) ff[i][i][1]=1;
      	for(int i=1;i<=n;i++)
      		for(int j=2;j<=m && j<=i;j++)
      			for(int x=1;x<=i/j;x++)
      				ff[x][i][j]=f[i-x-(x-1)*(j-1)][j-1];//i-x-(x-1)*(j-1)的意思:第一个盒子放x个,并且后面每个盒子提前放x-1个 
      
      int xx=0;//xx表示之前提前放入的球的个数和 
      for(int i=1;i&lt;m;i++)//逐个确定每个盒子放的球数 
      {
      	int x=1;
      	while(k&gt;ff[x][n][m-i+1])
      	{
      		k-=ff[x][n][m-i+1];
      		x++;
      	}
      	printf("%d "&#44;x+xx);
      	xx+=x-1;
      	n=n-(x +  (x-1)*(m-i) );//第i个盒子加入x个,并且后面每个盒子提前加x-1个 
      }
      printf("%d\n"&#44;n+xx);
      return 0; 
      

      }

      </p>






      • 1

      *【动态规划:状态设计DP(难度:7)】第几个数的划分(加强版)

      信息

      ID
      776
      时间
      1000ms
      内存
      128MiB
      难度
      7
      标签
      递交数
      20
      已通过
      8
      上传者