蓝桥杯每日一真题—— [蓝桥杯 2019 省 A] 糖果(状态压缩dp)

Posted 孤独时代的c0re

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了蓝桥杯每日一真题—— [蓝桥杯 2019 省 A] 糖果(状态压缩dp)相关的知识,希望对你有一定的参考价值。

[蓝桥杯 2019 省 A] 糖果

题目描述

糖果店的老板一共有 M M M 种口味的糖果出售。为了方便描述,我们将 M M M 种口味编号 1 1 1 M M M

小明希望能品尝到所有口味的糖果。遗憾的是老板并不单独出售糖果,而是 K K K 颗一包整包出售。

幸好糖果包装上注明了其中 K K K 颗糖果的口味,所以小明可以在买之前就知道每包内的糖果口味。

给定 N N N 包糖果,请你计算小明最少买几包,就可以品尝到所有口味的糖果。

输入格式

第一行包含三个整数 N N N M M M K K K

接下来 N N N 行每行 K K K 这整数 T 1 , T 2 , ⋯   , T K T_1,T_2, \\cdots ,T_K T1,T2,,TK,代表一包糖果的口味。

输出格式

一个整数表示答案。如果小明无法品尝所有口味,输出 − 1 -1 1

样例 #1

样例输入 #1

6 5 3
1 1 2
1 2 3
1 1 3
2 3 5
5 4 2
5 1 2

样例输出 #1

2

提示

对于 30 % 30\\% 30% 的评测用例, 1 ≤ N ≤ 20 1 \\le N \\le 20 1N20

对于所有评测样例, 1 ≤ N ≤ 100 1 \\le N \\le 100 1N100 1 ≤ M ≤ 20 1 \\le M \\le 20 1M20 1 ≤ K ≤ 20 1 \\le K \\le 20 1K20 1 ≤ T i ≤ M 1 \\le T_i \\le M 1TiM

蓝桥杯 2019 年省赛 A 组 I 题。


思路:

你一看这个题,数据那么少,N<=20就,而且这个要求是买所有的糖果所以只要知道这种糖果有没有就可以了就是0/1。那这样为了节省空间就可以用二进制0/1来表示这个糖果是不是买了/ 所以这就是一个状态压缩dp。


  1. 首先 初始化 不会初始化直接先去学学位运算,学学状压dp去,因为要求最小值所以就把dp初始化为最大值,在初始化的时候建议0x3f来初始化相加的时候不会超int
int n, m, k, x;
int a[400];
int dp[1 << 21];
int main()

	cin >> n >> m >> k;
	for (int i = 1; i <= n; i++)
	
		for (int j = 1; j <= k; j++)
		
			// 读入每包糖果
			cin >> x;
			a[i] |= 1 << (x - 1);
		
	

	memset(dp, 0x3f, sizeof(dp)); // 初始化dp为最大值

	dp[0] = 0; // 最小访问次数
  1. 我们要访问什么呢,1,要访问每包糖果;2,要访问每个状态所以遍历就这么写
for (int i = 1; i <= n; i++)//访问每包糖果
	
		for (int j = 0; j < (1 << m); j++)//访问每个状态
		
		
	

  1. dp方程怎么写:访问每包糖果可以买也可以不买,如果我们买了那dp就是当前状态加一。那这个买了的要和谁比较呢,要和能买到这个状态的之前我们可能已经存在的状态比较 。比如你之前已经买了这个糖了而且用的次数比dp+1少就不用买,直接用原来的状态;(有点啰嗦。。。。)就原来得到这个糖果的状态所需的次数和当前的次数+1比较就可以了选最小值
			if (dp[j] > n)
				continue;
			
			// 将原来得到糖果所需的次数与当前次数+1(要这袋糖果)比较并赋值
			dp[j | a[i]] = min(dp[j | a[i]], dp[j] + 1);
  1. 要是大于糖的袋数就直接-1没有直接输出,完事。
	// (1<<m)-1 表示都是1 也就是都买到的状态。
	if (dp[(1 << m) - 1] > n)
        		cout << -1;
	//>n就买不到了

	else
        		cout << dp[(1 << m) - 1];
	//直接输出次数


全部代码

#include <bits/stdc++.h>
using namespace std;
int n, m, k, x;
int a[400];
int dp[1 << 21];
int main()

	cin >> n >> m >> k;
	for (int i = 1; i <= n; i++)
	
		for (int j = 1; j <= k; j++)
		
			// 读入每包糖果
			cin >> x;
			a[i] |= 1 << (x - 1);
		
	

	memset(dp, 0x3f, sizeof(dp)); // 初始化dp为最大值

	dp[0] = 0; // 最小访问次数

	for (int i = 1; i <= n; i++)//访问每包糖果
	
		for (int j = 0; j < (1 << m); j++)//访问每个状态
		
			// 如果最小次数已经大于n(买不到喽)
			if (dp[j] > n)
				continue;
			
			// 将原来得到糖果所需的次数与当前次数+1(要这袋糖果)比较并赋值
			dp[j | a[i]] = min(dp[j | a[i]], dp[j] + 1);
		
	

	// (1<<m)-1 表示都是1 也就是都买到的状态。
	if (dp[(1 << m) - 1] > n)
        		cout << -1;
	//>n就买不到了

	else
        		cout << dp[(1 << m) - 1];
	//直接输出次数

	return 0;



公告栏

本人从洛谷做的,要是别的oj通不过直接评论区留言~~~,洛谷有一些时候写错了直接给我ac了。
侵权联系删除。

蓝桥杯每日一真题—— [蓝桥杯 2021 省 AB2] 完全平方数(数论,质因数分解)

文章目录

[蓝桥杯 2021 省 AB2] 完全平方数

题目描述

一个整数 a a a 是一个完全平方数,是指它是某一个整数的平方,即存在一个 整数 b b b,使得 a = b 2 a=b^2 a=b2

给定一个正整数 n n n,请找到最小的正整数 x x x,使得它们的乘积是一个完全平方数。

输入格式

输入一行包含一个正整数 n n n

输出格式

输出找到的最小的正整数 x x x

样例 #1

样例输入 #1

12

样例输出 #1

3

样例 #2

样例输入 #2

15

样例输出 #2

15

提示

对于 30 % 30 \\% 30% 的评测用例, 1 ≤ n ≤ 1000 1 \\leq n \\leq 1000 1n1000,答案不超过 1000 1000 1000

对于 60 % 60 \\% 60% 的评测用例, 1 ≤ n ≤ 1 0 8 1 \\leq n \\leq 10^8 1n108,答案不超过 1 0 8 10^8 108

对于所有评测用例, 1 ≤ n ≤ 1 0 12 1 \\leq n \\leq 10^12 1n1012,答案不超过 1 0 12 10^12 1012

蓝桥杯 2021 第二轮省赛 A 组 G 题(B 组 H 题)。

思路:

这一看直接暴力就只能得一点点分,我还数论学的不太好先暴力得了30分。然后开始想办法吧!
没办法。。。看答案吧。。。

理论补充:完全平方数的一个性质:完全平方数的质因子的指数一定为偶数

1.唯一分解定理任意一个数 n,它都可以分解为若干个质数的乘积。

2.需要知道完全平方数的一个性质:完全平方数的质因子的指数一定为偶数。附上大佬的证明过
程:

最终思路:

对n进行质因数分解,如果质因数的指数为奇数的话就在x中乘以这个质因子这样,可以让指数保持偶数,如果是偶数那就不用管它~~~~
1.分解质因子:

for (long long i = 2; i * i <= n; i++)
    
        if (n % i == 0)
        
            cnt++;//记录有多少个因子,后面好遍历
        

        while (n % i == 0)
        
            a[cnt] = i;//a数组存因子
            g[cnt]++;//g数组存因子指数
            n = n / i;
        
    

    if (n > 1)
    
        a[++cnt] = n;
        g[cnt]++;
    //考虑没分解完的情况

2,根据性质得出答案:

  for (int i = 1; i <= cnt; i++)//遍历如果有奇数就让原来的n*ans*这个奇数质因子也就是让ans*这个奇数质因子
    
        if (g[i] % 2)
        
            ans = ans * a[i];
        
    
    cout << ans;

小插曲:

质因数分解写错了最后输出了和n一样的数竟然得了60分!!

全部代码

#include <iostream>
using namespace std;

long long n, ans = 1, g[1000], a[1000], cnt;
int main()

    cin >> n;
    // 首先对n进行质因数分解
    for (long long i = 2; i * i <= n; i++)
    
        if (n % i == 0)
        
            cnt++;//记录有多少个因子,后面好遍历
        

        while (n % i == 0)
        
            a[cnt] = i;//a数组存因子
            g[cnt]++;//g数组存因子指数
            n = n / i;
        
    

    if (n > 1)
    
        a[++cnt] = n;
        g[cnt]++;
    //考虑没分解完的情况
    //完全平方数的质因子的指数一定为偶数
    for (int i = 1; i <= cnt; i++)//遍历如果有奇数就让原来的n*ans*这个奇数质因子也就是让ans*这个奇数质因子
    
        if (g[i] % 2)
        
            ans = ans * a[i];
        
    
    cout << ans;
    system("pause");
    return 0;


以上是关于蓝桥杯每日一真题—— [蓝桥杯 2019 省 A] 糖果(状态压缩dp)的主要内容,如果未能解决你的问题,请参考以下文章

蓝桥杯C/C++每日一练之字母图形

蓝桥杯C/C++每日一练之数列特征

蓝桥杯省赛真题05python计算 青少年组蓝桥杯python编程省赛真题解析

蓝桥杯省赛真题04python输出数字 青少年组蓝桥杯python编程省赛真题解析

蓝桥杯省赛真题09python邮箱密码 青少年组蓝桥杯python编程省赛真题解析

蓝桥杯省赛真题09python邮箱密码 青少年组蓝桥杯python编程省赛真题解析