CCF-CSP 202209 赛题练习

Posted ZSYL

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CCF-CSP 202209 赛题练习相关的知识,希望对你有一定的参考价值。

CCF-CSP 202209 赛题练习

如此编码

已知某次测验包含 n 道单项选择题,其中第 i 题(1≤i≤n)有 ai 个选项,正确选项为 bi,满足 ai≥2 且 0≤bi<ai。比如说,ai=4 表示第 i 题有 4 个选项,此时正确选项 bi 的取值一定是 0、1、2、3 其中之一。

首先定义一个辅助数组 ci,表示数组 ai 的前缀乘积。当 1≤i≤n 时,满足:ci=a1×a2×⋯×ai

特别地,定义 c0=1。

m = c 0 ∗ b 1 + c 1 ∗ b 2 . . . . . m=c_0*b_1+c_1*b_2..... m=c0b1+c1b2.....

输入格式

从标准输入读入数据。

输入共两行。

第一行包含用空格分隔的两个整数 n 和 m,分别表示题目数量和顿顿老师的神秘数字。

第二行包含用空格分隔的 n 个整数 a1,a2,⋯,an,依次表示每道选择题的选项数目。

输出格式

输出到标准输出。

输出仅一行,包含用空格分隔的 n 个整数 b1,b2,⋯,bn,依次表示每道选择题的正确选项。

样例1输入

15 32767
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2

样例1输出

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

#include<bits/stdc++.h>
using namespace std;

const int N = 21;
int n, m;
int a[N];
int b[N];
int c = 1, tc = 1;

int main() 
    cin >> n >> m;
    for (int i = 0; i < n; i++) 
        cin >> a[i];
    
    for (int i = 0; i < n; i++) 
        tc = a[i]*c;   // 计算C1
        cout << int((m%tc) / c) << ' ';  // 除法相当于把前一个乘积减去了
        c = tc;
    
    return 0;

代码来源:Link

何以包邮?

输入n,n本书,m:sum>=m时包邮,求满足包邮的最低费用。

4 100
20
90
60
60

110

DFS

  • 对于每本书,都有不选两种方案,可以对应一棵完全二叉树
  • 遍历所有书的两种方案,找到最小值,采用dfs算法
#include<bits/stdc++.h>
using namespace std;

const int N = 35;
int n, x;
int price[N];
int ans = 1e9;

void dfs(int k, int sum) 
    if (sum >= x) 
        ans = min(ans, sum);  // 更新最小值
    if (k > n)
        return;
    dfs(k+1, sum + price[k]);  // 选择这本书
    dfs(k+1, sum);  // 不选择
    

int main() 
    cin >> n >> x;
    for (int i = 1; i <= n; i++)
        cin >> price[i];
    dfs(1, 0);  // 从第一本开始
    cout << ans;
    return 0;

  • 在思路二的基础上,对二叉树进行剪枝
  • 剪枝思路:当前节点sum加上剩余节点的所有值之和已经小于x了,进行剪枝
  • 求剩余节点的所有值,可以采用前缀和的思想
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 50;
int n,x;
int price[N];//价格
int sum_price[N];//前缀和
int ans = 1e9;
void dfs(int k,int sum)

    
    if(sum+sum_price[n]-sum_price[k-1]<x)//sum_price[n]-sum_price[k-1]为剩余节点的所有值的和
    
        return;
    
    if(sum>=x)
    
        ans = min(sum,ans);//更新最小值
    
    if(k>n)
    
        return;
    
    dfs(k+1,sum+price[k]);//选择这本书
    dfs(k+1,sum);//不选择这本书

int main()

    cin>>n>>x;
    for(int i=1;i<=n;i++)
    
        cin>>price[i];
        sum_price[i]=sum_price[i-1]+price[i];//前缀和
    
    dfs(1,0);//从第一本书开始
    cout<<ans<<endl;

代码来源Link

DP思路

这个题就是一个01背包问题,书的价格既是价值又是体积。

注意用一个变量sum表示当前所有书的价格,这就是我们当前的体积

#include <bits/stdc++.h>
using namespace std;
const int N = 300010;
int n, m, v, sum;
int f[N];
int main() 
    cin >> n >> m;
    for (int i = 0; i < n; i++) 
        cin >> v;
        sum += v;
        for (int j = sum; j >= v; j--) 
            f[j] = max(f[j], f[j - v] + v);
        
    
    for (int i = m;; i++) 
        if (f[i] >= m) 
            cout << f[i];
            break;
        
    
    return 0;

Reference

Link

加油!

感谢!

努力!

以上是关于CCF-CSP 202209 赛题练习的主要内容,如果未能解决你的问题,请参考以下文章

CCF-CSP 201604 赛题训练

CCF-CSP 201709 赛题训练

CCF-CSP 201712 赛题训练

CCF-CSP 202203 赛题训练

CCF-CSP 201612 赛题训练

CCF-CSP 201609 赛题训练