首页 > 其他分享 >度的数量

度的数量

时间:2024-05-04 15:46:37浏览次数:11  
标签:cnt last int res pos 数量 dp

code(记忆化搜索)

#include<iostream>
#include<cstring>
using namespace std;
const int N = 35;//因为Y最大为2的31次方,所以要尽量开比31大 

int dp[N][N],a[N],k,b,len;
int dfs(int pos,int cnt,int limit){//pos代表第几位数,cnt代表1的个数,limit代表是否有限制 
	if(!pos) return cnt==k;//
	if(!limit&&dp[pos][cnt]!=-1) return dp[pos][cnt];//没有限制且dp数组被访问过 
	int res = 0,up = limit ? a[pos] : b-1;//res为方案个数,up代表上界 
	for(int i = 0;i <= up;i++){
		if((i==1&&cnt==k) || i > 1) continue;
//(条件判断)当此位为1且1的个数满足题目所给k或此位数字大于1 
		res += dfs(pos-1,cnt+(i==1),limit&&i==up);
	} 
	return limit?res:dp[pos][cnt] = res;
	//有限制直接返回方案数,无限制更新数组dp 
}
int cal(int x)
{
	memset(dp,-1,sizeof(dp));//初始化dp数组为-1 
	len = 0;//记录转换为某进制的位数 
	while(x){
		a[++len] = x%b;
		 x/=b;
	}
	return dfs(len,0,1);
}
int main(){
	int l,r;
	cin>>l>>r>>k>>b;
	cout<<cal(r)-cal(l-1)<<endl;
	return 0;
}


递推方法
在分析之前,了解一个组合数递推公式

分析过程

  • 第一步:数x转化为B进制,记为N,将转化后的B进制数中的每一位存入一个nums数组

  • 第二步:nums数组中从高位到低位依次进行分类讨论,对于第i位数字x有3种情况(k含义见题意,last表示第i位之前的所有位取过的1的个数

    • x = 0,此时第i位只能取0,不影响1的个数,贡献值为0,后面所有位(共i位,因为下标从0开始)可取k-last个1,直接讨论后面i位即可

    • x = 1:此时可以取0或1,当第i位取0时,后面i位都可以随意取值,可取k-last个1
      当取1的时候,后面i位要在小于题目给定数(k)的前提下取值,在进行讨论,后面i位不能随便取,也就不是组合数(只能取k-last-1个1

    • x > 1:i位上可取1,0,并且后面 i 位可以随意取k-last-1个1,除了0、1,其他值都不能取,其他值不符合题意

    图表结合

预处理f[i][j]表示从剩下i位选择j个1的方案数,那么在(i,j)这个状态,
对于第i位,填1的话,那么接下来的状态为f[i-1][j-1],
对于第i位,填0的话,那么接下来的状态就是f[i-1][j],那么状态转移方程为f[i][j] = f[i-1][j] + f[i-1][j-1] ,
而初始状态即j=0,f[i][0] = 1(好好理解

eg.预处理过程如下所示

dp(n)求出0~n上的满足题意的方案数

#include<iostream>
#include<vector>
using namespace std;
int k,B;
const int N= 35;
int f[N][N];
void init(){//求组合数 
	for(int i=0;i<N;i++){
		for(int j = 0;j<=i; j++){
			if(!j) f[i][j] = 1;
			else f[i][j] = f[i-1][j] + f[i-1][j-1];
		}
	}
}
int dp(int n){
	if(!n) return 0;//若n=0,直接返回0 
	vector<int> nums;
	while(n)   while(n){
        nums.push_back(n%B);
        n/=B;
    }
	int res = 0;
	int last = 0;//表示已经取了多少个1 
	for(int i = nums.size()-1; i>=0; i--){
		int x = nums[i];
		if(x){//大于1的方块和等于1的方块贡献值 
			res +=f[i][k-last];//加上第i位取0时的组合数, 
			if(x>1){//x大于1时,当此位取1时组合数 
				if(k - last - 1 >= 0) res += f[i][k-last-1];
				break;
			}
			else{//若x=1,则i位取1时,还要进行讨论, 后面i位不能随便取,也就不是组合数 
				last++;
				if(last>k) break;
			}
		}
		if(!i&&last==k) res++;//最右侧分支上的方案, 
	}
	return res;
}
int main(){
	init();
	int l,r;
	cin>>l>>r>>k>>B;
	cout<<dp(r)-dp(l-1)<<endl;
}

标签:cnt,last,int,res,pos,数量,dp
From: https://www.cnblogs.com/6Luffy6/p/18172372

相关文章

  • 容器化部署Tengine worker数量问题
    当容器化部署Tengine时,worker数量默认是cpu数量。https://tengine.taobao.org/document_cn/core_cn.html对应/etc/nginx/nginx.conf数量配置是4。容器中cpu数量是节点cpu数量,Nginx不需要这么多worker子进程,指定worker_processes是2即可。......
  • 2024-05-01:用go语言,给定两个长度为偶数n的整数数组nums1和nums2, 分别移除它们各自的一
    2024-05-01:用go语言,给定两个长度为偶数n的整数数组nums1和nums2,分别移除它们各自的一半元素,将剩下的元素合并成集合s。找出集合s中可能包含的最多元素数量。输入:nums1=[1,2,3,4,5,6],nums2=[2,3,2,3,2,3]。输出:5。答案2024-05-01:chatgpt题目来自leetcode3002。大体......
  • mysql按季度统计数量金额
    需求:oms_order-订单表:order_code-订单号,sales_time-销售时间oms_order_shopify_refund-订单退款表:order_code-订单号,refund_time-退款时间oms_order_product:order_code-订单号,seller_sku-商品编码,buy_quantity-售出数量,refund_quantity-退货数量查询订单时间按季度统计售出数量,并......
  • PeLK:101 x 101 的超大卷积网络,同参数量下反超 ViT | CVPR 2024
    最近,有一些大型内核卷积网络的研究,但考虑到卷积的平方复杂度,扩大内核会带来大量的参数,继而引发严重的优化问题。受人类视觉的启发,论文提出了外围卷积,通过参数共享将卷积的复杂性从\(O(K^{2})\)降低到\(O(\mathrm{log}K)\),有效减少90%以上的参数数量并设法将内核尺寸扩大到......
  • 35天【代码随想录算法训练营34期】第八章 贪心算法 part04 ( ● 860.柠檬水找零 ● 4
    860.柠檬水找零classSolution:deflemonadeChange(self,bills:List[int])->bool:amt_five=0amt_ten=0amt_twenty=0foriinbills:ifi==5:amt_five+=1elifi==10:......
  • 每天发射的卫星数量
    #defis_valid(seq,n,last_element=0):##print(seq[-1]//2)##print(last_element)#iflen(seq)==1:#returnTrue#iflast_element>seq[-1]//2:#returnFalse##returnis_valid(seq,n,last_element+1)......
  • 100294. 统计特殊字母的数量 I
     100294. 统计特殊字母的数量I 显示英文描述 我的提交返回竞赛 通过的用户数3108尝试过的用户数3161用户总通过次数3158用户总提交次数4364题目难度Easy给你一个字符串 word。如果 word 中同时存在某个字母的小写形式和大写形式,则称这个字母为 ......
  • 100291. 统计特殊字母的数量 II
    给你一个字符串 word。如果 word 中同时出现某个字母 c 的小写形式和大写形式,并且 每个 小写形式的 c 都出现在第一个大写形式的 c 之前,则称字母 c 是一个 特殊字母 。返回 word 中 特殊字母 的数量。 示例1:输入:word="aaAbcBC"输出:3解释:特殊字母......
  • 银行笔试——数量关系
    竟然还有三级等差数列这样神奇的存在 等比数列  位数这样反复横跳的可能是等比保证符号一正一扶,要是连续负或正则可能是位数问题 ......
  • 2024-04-18 使用webpack减少打包文件数量
    减少Webpack打包文件的数量通常涉及多个策略和配置选项。下面是一些具体的方法和示例代码,帮助你实现这一目标:1.代码分割(CodeSplitting)使用动态导入(import())语法将代码分割成多个块,这样Webpack会为每个块生成一个单独的文件。//假设我们有一个大型的组件库//而不是......