CCF-CSP 202209-1 如此编码

CCF-CSP 202209-1 如此编码

  • 题目要求
    • ‍⬛问题背景
    • ‍⬛问题描述
    • ‍⬛输入格式
    • ‍⬛输出格式
    • ‍⬛样例说明
      • 样例1输入
      • 样例1输出
      • 样例2输入
      • 样例2输出
      • 样例3输入
      • 样例3输出
      • 样例3解释
    • ‍⬛子任务
    • ‍⬛提示
  • 问题解决
    • 满分代码(含逐行代码解释)
      • C++
      • Python
    • 场景拓展

题目要求

‍⬛问题背景

某次测验后,顿顿老师在黑板上留下了一串数字 23333 便飘然而去。凝望着这个神秘数字,小 P 同学不禁陷入了沉思……

‍⬛问题描述

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

顿顿老师设计了如下方式对正确答案进行编码,使得仅用一个整数 m m m 便可表示 b 1 , b 2 , ⋅ ⋅ ⋅ , b n b_1,b_2,···,b_n b1,b2,⋅⋅⋅,bn

首先定义一个辅助数组 c i c_i ci,表示数组 a i a_i ai 的前缀乘积。当 1 ≤ i ≤ n 1 \leq i \leq n 1in 时,满足:

c i = a 1 × a 2 × ⋅ ⋅ ⋅ × a i c_i=a_1×a_2×···×a_i ci=a1×a2×⋅⋅⋅×ai

特别地,定义 c 0 = 1 c_0=1 c0=1

于是 m m m 便可按照如下公式算出:

m = ∑ i = 1 n c i − 1 × b i = c 0 × b 1 + c 1 × b 2 + ⋅ ⋅ ⋅ + c n − 1 × b n m=\sum_{i=1}^{n} c_{i-1}×b_i \\ \quad =c_0×b_1+c_1×b_2+···+c_{n-1}×b_n m=i=1nci1×bi=c0×b1+c1×b2+⋅⋅⋅+cn1×bn

易知, 0 ≤ m < c n 0 \leq m < c_n 0m<cn,最小值和最大值分别当 b i b_i bi 全部为 0 和 b i = a i − 1 b_i=a_i - 1 bi=ai1 时取得。

试帮助小 P 同学,把测验的正确答案 b 1 , b 2 , ⋅ ⋅ ⋅ , b n b_1,b_2,···,b_n b1,b2,⋅⋅⋅,bn 从顿顿老师留下的神秘整数 m m m 中恢复出来。

‍⬛输入格式

从标准输入读入数据。

输入共两行。

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

第二行包含用空格分隔的 n n n 个整数 a 1 , a 2 , ⋅ ⋅ ⋅ , a n a_1,a_2,···,a_n a1,a2,⋅⋅⋅,an,依次表示每道选择题的选项数目。

‍⬛输出格式

输出到标准输出。

输出仅一行,包含用空格分隔的 n n n 个整数 b 1 , b 2 , ⋅ ⋅ ⋅ , b n b_1,b_2,···,b_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

样例2输入

4 0
2 3 2 5

样例2输出

0 0 0 0

样例3输入

7 23333
3 5 20 10 4 3 10

样例3输出

2 2 15 7 3 1 0

样例3解释

i 1 2 3 4 5 6 7
a i a_i ai 3 5 20 10 4 3 10
b i b_i bi 2 2 15 7 3 1 0
c i − 1 c_{i-1} ci1 1 3 15 300 3000 12000 36000

‍⬛子任务

50% 的测试数据满足: a i a_i ai 全部等于 2,即每道题均只有两个选项,此时 c i = 2 i c_i=2^i ci=2i

全部的测试数据满足: 1 ≤ n ≤ 20 1 \leq n \leq 20 1n20 a i ≥ 2 a_i \geq 2 ai2 c n ≤ 1 0 9 c_n \leq 10^9 cn109(根据题目描述中的定义 c n c_n cn 表示全部 a i a_i ai 的乘积)。

‍⬛提示

对任意的 1 ≤ j ≤ n 1 \leq j \leq n 1jn,因为 c j + 1 , c j + 2 , ⋅ ⋅ ⋅ c_{j+1},c_{j+2},··· cj+1,cj+2,⋅⋅⋅ 均为 c j c_j cj 的倍数,所以 m m m 除以 q q q 的余数具有如下性质:
m % c j = ∑ i = 1 n c i − 1 × b i m\%c_j=\sum_{i=1}^{n} c_{i-1}×b_i m%cj=i=1nci1×bi
其中 % \% % 表示取余运算。令 j j j 取不同的值,则有如下等式:
m % c 1 = c 0 × b 1 m\%c_1=c_{0}×b_1 m%c1=c0×b1
m % c 2 = c 0 × b 1 + c 1 × b 2 m\%c_2=c_{0}×b_1+c_{1}×b_2 m%c2=c0×b1+c1×b2
m % c 3 = c 0 × b 1 + c 1 × b 2 + c 2 × b 3 m\%c_3=c_{0}×b_1+c_{1}×b_2+c_{2}×b_3 m%c3=c0×b1+c1×b2+c2×b3
⋅ ⋅ ⋅ ··· ⋅⋅⋅

问题解决

满分代码(含逐行代码解释)

C++

#include
using namespace std;

int main(){
	//输入 
	int n, a[100001], b[100001];
	long long int m;
	cin >> n >> m;
	for(int i = 0; i < n; i++){
		cin >> a[i];
	}
	//计算 
	long long int c = 1;
	long long int temp;
	for(int i = 0; i < n; i++){
		//计算过程按照题目要求的来 
		temp = c;
		c *= a[i];
		b[i] = ((m % c) - (m % temp)) / temp; 
		//计算m除以c的余数,然后减去m除以temp的余数,最后再除以temp
	}
	//输出
	for(int i = 0; i < n; i++){
		cout << b[i] << " ";
	}
	return 0;
} 

Python

#代码逻辑与C++完全相同,不再一一赘述
# 输入
n, m = map(int, input().split())
a = list(map(int, input().split()))
b = [0] * n

# 计算
c = 1
for i in range(n):
    temp = c
    c *= a[i]
    b[i] = ((m % c) - (m % temp)) // temp

# 输出
for i in range(n):
    print(b[i], end=" ")

场景拓展

本题代码适用于一类与模运算相关的题型。这类题型通常涉及到对给定数值范围内的所有数进行某种操作,并且需要计算每个数在该操作下的结果。具体来说,这段代码适用于以下类型的题目:

  • 数论问题:求解某个数在给定范围内的取值情况,如求解在区间[1, n]中能被a整除但不能被b整除的数的个数。
  • 排列组合问题:求解某个数的阶乘、组合数等相关问题,如求解n个数的全排列中,m在某个位置的个数。
  • 动态规划问题:求解某个状态的转移方程,如背包问题、最长公共子序列等。

你可能感兴趣的:(CCF-CSP,算法,c++,python)