当前位置: 首页 > news >正文

《CF525E Anya 和立方体》

题目描述

Anya 喜欢折叠和粘贴。今天,她决定这样做。

Anya 有n立方体排成一行,编号为1自n从左到右,上面写有自然数。她还k带有感叹号的贴纸。我们知道贴纸的数量不会超过立方体的数量。

Anya 可以在立方体上贴一个感叹号,并得到写在立方体上的数字的阶乘。例如,如果一个 cube 读取5,然后在粘贴后显示为5!,它等于120.

您需要帮助 Anya 数一数有多少种方法可以选择一些方块,然后最多粘在一些选定的方块上k感叹号,以便粘贴后写在所选立方体上的数字之和等于S.Anya 最多可以在每个立方体上贴上一个感叹号。你能做到吗?

如果两种方法具有相同的所选多维数据集集和同一组带感叹号的多维数据集,则认为这两种方式相同。

输入格式

输入的第一行包含三个以空格分隔的整数n,kS(1≤ n≤25,0≤ k≤ n,1≤ S≤1016)— Anya 拥有的立方体数量和贴纸数量,以及她需要获得的总和。

第二行包含n正整数一个​ (1≤一个​≤109)——写在立方体上的数字。输入中的多维数据集按从左到右的顺序描述,从第一个多维数据集开始。

多个多维数据集可以包含相同的数字。

输出格式

输出选择一定数量的立方体的方法数,并在其中一些立方体上贴上感叹号,使数字之和等于给定的数字S.

隐藏翻译

题意翻译

给你 n 个数,n≤25。 初始序列为 一个​,0≤ 一个​≤109。

你有 k 个 !,每个 ! 可以使序列中的一个数变成 一个​!。 (同一个数至多变一次)

例如 5!=120。

求:选出任意个数使他们和的等于 S 的方案数

输入格式

第一行 n,k,S

第二行 n 个数,分别代表 一个​。

输出

一行一个整数,选出数的合法方案数。

感谢 @s_a_b_e_r 提供的翻译。

输入输出样例

输入 #1复制

<span style="color:#404040"><span style="background-color:#fafafa">2 2 30
4 3
</span></span>

输出 #1复制

<span style="color:#404040"><span style="background-color:#fafafa">1
</span></span>

输入 #2复制

<span style="color:#404040"><span style="background-color:#fafafa">2 2 7
4 3
</span></span>

输出 #2复制

<span style="color:#404040"><span style="background-color:#fafafa">1
</span></span>

输入 #3复制

<span style="color:#404040"><span style="background-color:#fafafa">3 1 1
1 1 1
</span></span>

输出 #3复制

<span style="color:#404040"><span style="background-color:#fafafa">6
</span></span>

说明/提示

在第一个示例中,唯一的方法是选择两个立方体并在每个立方体上贴上一个感叹号。

在第二个示例中,唯一的方法是选择两个多维数据集,但不要在其中任何一个多维数据集上粘贴感叹号。

在第三个示例中,可以通过三种方式选择任何立方体,我们也可以选择粘贴或不在其上粘贴感叹号。因此,方法的总数为 6 种。

代码实现:

#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
using namespace std;
typedef long long LL;

// 计算阶乘,注意处理溢出情况
LL factorial(LL x) {
    LL res = 1;
    for (LL i = 2; i <= x; ++i) {
        res *= i;
    }
    return res;
}

// 生成所有可能的组合及其和与使用的感叹号数量
void generate(vector<pair<LL, LL> >& cubes, map<LL, map<LL, LL> >& sums) {
    int n = cubes.size();
    for (int mask = 0; mask < (1 << n); ++mask) {
        LL sum_normal = 0;
        LL sum_fact = 0;
        int k_used = 0;
        
        for (int i = 0; i < n; ++i) {
            if (mask & (1 << i)) {
                sum_normal += cubes[i].first;
                sum_fact += cubes[i].second;
                k_used++;
            }
        }
        
        sums[sum_normal][k_used]++;
        if (sum_fact != sum_normal) {
            sums[sum_fact][k_used]++;
        }
    }
}

int main() {
    int n, k;
    LL S;
    cin >> n >> k >> S;
    
    vector<LL> a(n);
    for (int i = 0; i < n; ++i) {
        cin >> a[i];
    }
    
    // 预处理每个数的原始值和阶乘值(防止大数溢出)
    vector<pair<LL, LL> > cubes(n);
    for (int i = 0; i < n; ++i) {
        LL fact = (a[i] <= 20) ? factorial(a[i]) : a[i];
        cubes[i] = make_pair(a[i], fact);
    }
    
    // 分割数组为左右两部分
    int mid = n / 2;
    vector<pair<LL, LL> > left(cubes.begin(), cubes.begin() + mid);
    vector<pair<LL, LL> > right(cubes.begin() + mid, cubes.end());
    
    // 生成左右两部分的所有可能和
    map<LL, map<LL, LL> > left_sums, right_sums;
    generate(left, left_sums);
    generate(right, right_sums);
    
    // 合并结果,计算符合条件的方案数
    LL ans = 0;
    for (map<LL, map<LL, LL> >::const_iterator it1 = left_sums.begin(); it1 != left_sums.end(); ++it1) {
        LL sum_left = it1->first;
        const map<LL, LL>& left_k_counts = it1->second;
        
        LL target = S - sum_left;
        map<LL, map<LL, LL> >::const_iterator it2 = right_sums.find(target);
        if (it2 == right_sums.end()) {
            continue;
        }
        
        const map<LL, LL>& right_k_counts = it2->second;
        
        // 遍历所有可能的感叹号使用组合
        for (map<LL, LL>::const_iterator lk = left_k_counts.begin(); lk != left_k_counts.end(); ++lk) {
            for (map<LL, LL>::const_iterator rk = right_k_counts.begin(); rk != right_k_counts.end(); ++rk) {
                if (lk->first + rk->first <= k) {
                    ans += lk->second * rk->second;
                }
            }
        }
    }
    
    cout << ans << endl;
    return 0;
}

http://www.xdnf.cn/news/684019.html

相关文章:

  • 人工智能文科能学吗?
  • java每日精进 5.27【分布式锁】
  • 经典排序算法合集(下)
  • 【调试】【原理理解】ldm 和 diffusers 库的区别
  • 自动驾驶中的博弈式交互规划:从理论到实践
  • droidcam ivcam 电脑访问不到地址解决办法 把网线从猫插到路由上
  • 1. 编程语言进化史与JavaScript
  • 数据结构期末模拟试卷
  • app获取相册权限是否意味着所有相片都可随时读取?
  • 智能防护实战:从攻击成本看企业安全降本增效
  • Jpa 删除之@Version注解的实体类无法删除的问题
  • 远程办公如何实现零监控?深度拆解“吱吱”不会被监控的通讯办公软件
  • 在RK3588上实现YOLOv8n高效推理:从模型优化到GPU加速后处理全解析
  • 电机控制杂谈(26)——电机驱动系统的编码器的测速噪声
  • RK3568DAYU开发板-驱动平台驱动案例--PWM
  • 【Linux】(1)—进程概念-①冯诺依曼体系结构
  • 想查看或修改 MinIO 桶的匿名访问权限(public/private/custom)
  • java基础学习(十八)
  • 大模型微调(面经总结)
  • 代码风格指南
  • 聚焦北京央美备考画室:探寻实力之巅
  • 码蹄集——圆周率II、三个非负整数
  • PCB设计自检表
  • 基于心理健康与数字行为数据的多维度分析
  • JAVA运算符详解
  • Oracle向PG转移建议以及注意点
  • 57页 @《人工智能生命体 新启点》中國龍 原创连载
  • IvorySQL 核心技术解读:双 Parser 架构如何定义数据库兼容性?
  • python训练营打卡第36天
  • 竞赛小算法总结(二):gcdlcm,拓展欧几里得线性同余,逆元(含代码详解)