1019. General Palindromic Number (20)

本文介绍了一个C++程序,该程序实现了将十进制数转换为任意进制数的功能,并判断转换后的数是否为回文数。通过定义转换和判断函数,程序能够输出转换后的进制数及其是否为回文的结果。
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>

#include <cstring>
#include <string>
#include <queue>
#include <vector>

using namespace std;

int n,b;
int z[105],num=0;

void change()//转换进制模板,其中num是转换之后的位数
{
    do
    {
        z[num++]=n%b;
        n=n/b;
    }while(n!=0);
}
bool judge(int z[],int num)
{
    for(int i=0;i<num/2;i++)
    {
        if(z[i] != z[num-1-i])
            return false;
    }

    return true;
}
void pr()//打印
{
    for(int i=num-1;i>=0;i--)
    {
        if(i==num-1)
            printf("%d",z[i]);
        else
            printf(" %d",z[i]);
    }
}
int main()
{
   // freopen("in.txt","r",stdin);

    scanf("%d %d",&n,&b);
    change();
    if(judge(z,num))
    {
        printf("Yes\n");
        pr();
    }
    else
    {
        printf("No\n");
        pr();
    }

    return 0;
}

内容概要:本文系统介绍了标准化和软件知识产权的基础知识,涵盖标准化的基本概念、分类、标准代号、国际标准的采用原则及程度,重点讲解了信息技术标准化、ISO与IEC等国际标准化组织以及ISO9000和ISO/IEC15504等重要标准体系;在知识产权部分,详细阐述了知识产权的定义、分类及特点,重点分析了计算机软件著作权的主体、客体、权利内容、行使方式、保护期限及侵权认定,同时涉及商业秘密的构成与侵权形式、专利权的类型与申请条件,以及企业如何综合运用著作权、专利、商标和商业秘密等方式保护软件知识产权。; 适合人群:从事软件开发、项目管理、IT标准化或知识产权相关工作的技术人员与管理人员,以及备考相关资格考试的学习者;具备一定信息技术背景,希望系统掌握标准化与软件知识产权基础知识的专业人员。; 使用场景及目标:①帮助理解各类标准的分类体系及国际标准采用方式,提升标准化实践能力;②指导企业在软件研发过程中有效保护知识产权,规避法律风险;③为软件著作权登记、专利申请、技术保密等提供理论依据和操作指引。; 阅读建议:建议结合国家相关政策法规和实际案例进行深入学习,重点关注软件著作权与专利权的适用边界、标准制定流程及企业知识产权管理策略,强化理论与实践的结合。
这是一个 **子集和问题的变种**:我们需要统计所有非空子集(也可以是空集?看样例),使得子集元素之和是一个**回文数(palindromic number)**。 --- ## ✅ 题意解析 - 给定 `N` 个正整数(可能重复) - 你可以选择任意数量的数(1 到 N 个,即非空子集) - 求有多少种**选择方式(子集)**,其和为**回文数** - 子集不同 ⇨ 即使和相同也算不同(只要选的元素位置不同就算不同) 但注意:输入样例中: ``` 输入: 3 1 1 100 输出:3 ``` 我们来分析这个样例。 --- ## 🔍 样例分析:`[1, 1, 100]` 所有非空子集有 $2^3 - 1 = 7$ 个: | 子集 | 元素 | 和 | 是否回文 | |------|------|----|---------| | {1} | [1] | 1 | ✅ 是 | | {1} | [1] | 1 | ✅ 是 | | {100} | [100] | 100 | ❌ 否("100" ≠ "001") | | {1,1} | [1,1] | 2 | ✅ 是 | | {1,100} | [1,100] | 101 | ✅ 是 | | {1,100} | [1,100] | 101 | ✅ 是 | | {1,1,100} | [1,1,100] | 102 | ❌ 否 | 现在检查每个和是否是回文数: - 1 → 是 - 1 → 是 - 100 → 不是 - 2 → 是 - 101 → 是 - 101 → 是 - 102 → 不是 所以满足条件的子集有: 1. 第一个 1 → 和=1 2. 第二个 1 → 和=1 3. {1,1} → 和=2 4. {1,100}(第一个1+100)→ 和=101 5. {1,100}(第二个1+100)→ 和=101 共 **5 个** 但输出是 **3**! 这说明我们的理解有问题。 --- ## ❗ 重新思考:是不是相同的值视为同一种选择? 或者题目中的“ways”是指不同的**和值**? 但题目说:“how many ways you can choose the numbers”,应该是不同的子集算不同的方式。 然而输出是 `3`,不是 `5`。 ### 可能原因:题目认为两个 `1` 是不可区分的? 即数组 `[1,1,100]` 中有两个相同的 `1`,如果它们来自不同位置但值相同,在组合中视为相同? 但这与常规“子集计数”不符。 除非题目意思是:**不同的子集,即使元素相同、位置不同,但如果值一样,就合并?** 不,通常不会这样。 再试另一种可能性:我们列出所有**不同的和值**中,哪些是回文? - 和=1 → 回文 ✅ - 和=2 → 回文 ✅ - 和=101 → 回文 ✅ - 其他:100,102 → 不是 → 有 3 个**不同的回文和值** 但题目问的是“多少种选择方式”,不是“多少个回文和” → 所以不是这个解释。 --- ## 🚫 矛盾!我们得到 5,样例输出是 3 ### 新思路:也许题目不允许选单个数字?但样例用了单个 1 等等,再看一遍题目: > "you can choose 1,2,3,....or n of them" → 至少选一个 → 正确 > 输出是 3 只有当我们把两个 `1` 视为同一个,并且只算一次和=1 的情况时才可能。 但即便如此,还有: - 和=1(出现两次,但只算一次?) - 和=2({1,1}) - 和=101(出现两次,但只算一次?) → 如果按**不同的子集**算,是 5 → 如果按**不同的和值**算,是 3(1,2,101) → 所以很可能:**题目在问有多少个不同的回文和值?** 但题目原文是: > how many ways you can choose the numbers so that the sum of them is palindromic number. 这里的 “ways” 应该是子集的数量,而不是不同和的数量。 --- ## ✅ 正确解读:可能是 **LeetCode 类型的“子集去重”问题** 即:虽然有两个 `1`,但因为值相同,某些子集被视为相同? 例如,在集合 `{1,1,100}` 中,选择第一个 `1` 或第二个 `1` 被视为同一种方式? 但在标准算法题中,如果是**索引不同**,就是不同的子集。 除非题目明确说是“distinct subsets by value”。 但我们来看另一个角度:最大可能和是多少? - N ≤ 20,ai ≤ 100 → 最大和 = 20×100 = 2000 - 回文数范围小:从 1 到 2000 的回文数大约只有几百个 我们可以用 **折半搜索(Meet-in-the-Middle) + 回文判断** 来暴力枚举所有子集和,然后统计和为回文数的子集数量。 然后运行样例看看。 --- ## ✅ 重新计算样例(假设两个 1 是可区分的) 子集如下(设 a=1, b=1, c=100): 1. a → sum=1 ✅ 2. b → sum=1 ✅ 3. c → sum=100 ❌ 4. ab → sum=2 ✅ 5. ac → sum=101 ✅ 6. bc → sum=101 ✅ 7. abc → sum=102 ❌ → 总共 5 个满足条件 但输出是 3 ### 唯一可能:题目意思是——输出的是**有多少个不同的回文和值**? 即: - 和=1 → 回文 - 和=2 → 回文 - 和=101 → 回文 共 3 个不同的回文和值 → 输出 3 ✅ 这就对上了! --- ## ✅ 最终理解 题目问的是: > 有多少个**不同的和值 S**,使得存在某个非空子集,其和为 S,且 S 是回文数? 即:不是统计子集个数,而是统计**能构成的回文和值的种类数** 例如: - 和=1 可以构成 → 计 1 次 - 和=2 可以构成 → 计 1 次 - 和=101 可以构成 → 计 1 次 - 和=100 不行 → 不计 总数 = 3 --- ## ✅ 解法步骤 1. 使用位掩码或 DFS 枚举所有非空子集的和 2. 将所有可能的和存入一个集合(set)中 3. 遍历这个集合,判断每个和是否是回文数 4. 统计回文和的数量 由于 N ≤ 20,最多 $2^{20} \approx 1e6$ 种子集,完全可行 --- ## ✅ C++ 实现 ```cpp #include <iostream> #include <vector> #include <set> #include <string> #include <algorithm> using namespace std; // 判断一个数是否是回文数 bool isPalindrome(int n) { string s = to_string(n); string t = s; reverse(t.begin(), t.end()); return s == t; } int main() { int N; while (cin >> N) { vector<int> nums(N); for (int i = 0; i < N; ++i) { cin >> nums[i]; } set<int> possibleSums; // 枚举所有非空子集 for (int mask = 1; mask < (1 << N); ++mask) { int sum = 0; for (int i = 0; i < N; ++i) { if (mask & (1 << i)) { sum += nums[i]; } } possibleSums.insert(sum); } // 统计其中有多少个是回文数 int count = 0; for (int s : possibleSums) { if (isPalindrome(s)) { count++; } } cout << count << endl; } return 0; } ``` --- ## ✅ 再验证样例 输入:`[1, 1, 100]` 所有非空子集和: - 1 (from first 1) - 1 (second 1) → 已存在 - 100 - 1+1=2 - 1+100=101 - 1+100=101 → 已存在 - 1+1+100=102 → 集合:{1, 2, 100, 101, 102} 回文判断: - 1 → 是 - 2 → 是 - 100 → 否 - 101 → 是 - 102 → 否 → 共 3 个回文和值 → 输出 `3` ✅ --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值