2^k进制数(对每部分代码详解)

ops/2024/10/21 1:58:15/

2^k进制数

题目描述

r r r 是个 2 k 2^k 2k 进制数,并满足以下条件:

  • r r r 至少是个 2 2 2 位的 2 k 2^k 2k 进制数。

  • 作为 2 k 2^k 2k 进制数,除最后一位外, r r r 的每一位严格小于它右边相邻的那一位。

  • r r r 转换为二进制数 q q q 后,则 q q q 的总位数不超过 w w w

在这里,正整数 k , w k,w k,w 是事先给定的。

问:满足上述条件的不同的 r r r 共有多少个?

我们再从另一角度作些解释:设 S S S 是长度为 w w w 01 01 01 字符串(即字符串 S S S w w w 0 0 0 1 1 1 组成), S S S 对应于上述条件三中的 q q q。将 S S S 从右起划分为若干个长度为 k k k 的段,每段对应一位 2 k 2^k 2k 进制的数,如果 S S S 至少可分成 2 2 2 段,则 S S S 所对应的二进制数又可以转换为上述的 2 k 2^k 2k 进制数 r r r

例:设 k = 3 , w = 7 k=3,w=7 k=3,w=7。则 r r r 是个八进制数( 2 3 = 8 2^3=8 23=8 )。由于 w = 7 w=7 w=7,长度为 7 7 7 01 01 01 字符串按 3 3 3 位一段分,可分为 3 3 3 段(即 1 , 3 , 3 1,3,3 1,3,3,左边第一段只有一个二进制位),则满足条件的八进制数有:

2 2 2 位数:
高位为 1 1 1 6 6 6 个(即 12 , 13 , 14 , 15 , 16 , 17 12,13,14,15,16,17 12,13,14,15,16,17 ),
高位为 2 2 2 5 5 5 个,
…,
高位为 6 6 6 1 1 1 个(即 67 67 67 )。
6 + 5 + … + 1 = 21 6+5+…+1=21 6+5++1=21 个。

3 3 3 位数:
高位只能是 1 1 1
2 2 2 位为 2 2 2 5 5 5 个(即 123 , 124 , 125 , 126 , 127 123,124,125,126,127 123,124,125,126,127 ),
2 2 2 位为 3 3 3 4 4 4 个,
…,
2 2 2 位为 6 6 6 1 1 1 个(即 167 167 167 )。
5 + 4 + … + 1 = 15 5+4+…+1=15 5+4++1=15 个。

所以,满足要求的 r r r 共有 36 36 36 个。

输入格式

一行两个正整数 k , w k,w k,w 用一个空格隔开:

输出格式

一行一个个正整数,为所求的计算结果。
即满足条件的不同的 r r r 的个数(用十进制数表示),要求不得有前导零,各数字之间不得插入数字以外的其他字符(例如空格、换行符、逗号等)。

(提示:作为结果的正整数可能很大,但不会超过 200 200 200 位)

样例 #1

样例输入 #1

3 7

样例输出 #1

36

提示

【数据范围】
1 ≤ k ≤ 9 1\le k \le 9 1k9
1 ≤ w ≤ 3 × 1 0 4 1\le w \le 3\times 10^4 1w3×104

题目来源

NOIP 2006 提高组 第四题(洛谷)

题解

#include<bits/stdc++.h>
using namespace std;// 比较两个高精度数a和b,a >= b返回1,否则返回0
inline bool comp(string a, string b) {if (a.size() < b.size())return 0;if (a.size() > b.size())return 1;for (int i = a.size() - 1; i >= 0; i--) {if (a[i] < b[i])return 0;if (a[i] > b[i])return 1;}return 1;
}// 求两个高精度数a和b的和
inline string sum(string a, string b) {if (comp(a, b) == 0)swap(a, b);string c = "";char x[2] = "";bool n = 0;int bpt = b.size() - 1;for (int i = a.size() - 1; i >= 0; i--) {if (b[bpt] < '0' || b[bpt] > '9')b[bpt] = '0';x[0] = a[i] + b[bpt] - '0';if (n == 1) {x[0]++;n = 0;}if (x[0] > '9') {x[0] -= 10;n = 1;}c.insert(0, x);bpt--;if (bpt < 0) {bpt = 0;b[0] = '0';}}if (n == 1)c.insert(0, "1");while (c[0] == '0')c.erase(0, 1);if (c.size() == 0)c.insert(0, "0");return c;
}// 求两个高精度数a和b的差(保证结果为正数)
string dif(string a, string b) {string c = "";char x[2] = "";bool n = 0;int bpt = b.size() - 1;for (int i = a.size() - 1; i >= 0; i--) {if (b[bpt] < '0' || b[bpt] > '9')b[bpt] = '0';x[0] = a[i] - b[bpt] + '0';if (n == 1) {x[0]--;n = 0;}if (x[0] < '0') {x[0] += 10;n = 1;}c.insert(0, x);bpt--;if (bpt < 0) {bpt = 0;b[0] = '0';}}while (c[0] == '0')c.erase(0, 1);if (c.size() == 0)c.insert(0, "0");return c;
}// 求高精度数a与整型数b的积
string mul(string a, int b) {string c = "";char x[2] = "";int n = 0, y;for (int i = a.size() - 1; i >= 0; i--) {y = 0;if (n > 0)y = n;n = (a[i] - '0') * b + y;x[0] = n % 10 + '0';n /= 10;if (x[0] > '9') {x[0] -= 10;n++;}c.insert(0, x);}while (n > 0) {x[0] = n % 10 + '0';n /= 10;c.insert(0, x);}while (c[0] == '0')c.erase(0, 1);if (c.size() == 0)c.insert(0, "0");return c;
}// 求高精度数a与整型数b的商
string div(string a, int b) {string c = "";char x[2] = "";int n = 0, y;for (int i = 0; i < a.size(); i++) {n *= 10;n += a[i] - '0';x[0] = n / b + '0';n %= b;c.insert(c.size(), x);}while (n > 0) {x[0] = n % 10 + '0';n /= 10;c.insert(0, x);}while (c[0] == '0')c.erase(0, 1);if (c.size() == 0)c.insert(0, "0");return c;
}// 把整型数转化成高精度数
string change(int num) {if (num == 0)return "0";string a = "";char c[2] = "";while (num > 0) {c[0] = num % 10 + '0';num /= 10;a.insert(0, c);}return a;
}// 覆盖(即用一个高精度数覆盖另一个高精度数)
void instead(string &s, string s0) {s.erase(0, s.size());s.insert(0, s0);
}string c[50000];
const int power[10] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512 }; // 打表计算2^nint main() {int k, w;cin >> k >> w;// 计算符合条件的两位数的数量c[2] = change((power[k] - 1) * (power[k] - 2) / 2);string ans = c[2];int most = min(w / k + (w % k == 0 ? 0 : 1), power[k] - 1); // most存储max(max不能定义)for (int i = 3; i <= most; i++) {if ((power[k] - i) % i == 0)c[i].insert(0, mul(c[i - 1], (power[k] - i) / i));elsec[i].insert(0, div(mul(c[i - 1], power[k] - i), i));ans = sum(ans, c[i]);}instead(c[most - 1], "1");int most2 = min(power[w % k] - 1, power[k] - most - 1);if (power[k] - most <= power[w % k] - 1 || most2 <= 0) {cout << ans;return 0;}// 特殊情况,如3 17,最大234567,上限6位3起,这时会误判ans = dif(ans, "1"); // 首位为max-1时要减掉for (int i = most; i < power[k] - 1 - most2; i++) {if (i % (i - most + 1) == 0)instead(c[i], mul(c[i - 1], i / (i - most + 1)));elseinstead(c[i], div(mul(c[i - 1], i), i - most + 1));ans = dif(ans, c[i]);}cout << ans;
}

http://www.ppmy.cn/ops/55833.html

相关文章

PIL,OpenCV,Pytorch处理图像时的通道顺序(颜色,长宽深)

项目颜色通道顺序长宽通道顺序数据类型取值范围PILRGBHWCndarray0-255 (byte)OpenCVBGRHWCndarray0-255 (byte)PyTorchRGB/BGR (取决于如何读取)(N)CHWtensor0-1 (float, 标准化后); 0-255 (int, 未标准化) 注意以下几点&#xff1a; 颜色通道顺序&#xff1a;PIL默认使用RGB顺…

SQLite 附加数据库

SQLite 附加数据库 SQLite 是一种轻量级的数据库管理系统,因其小巧、快速和易于使用而广受欢迎。在 SQLite 中,可以将多个数据库文件附加到单个数据库连接中,从而允许用户在不同的数据库之间轻松切换和操作数据。本文将详细介绍如何在 SQLite 中附加数据库,并探讨其使用场…

网页封装APP:让您的网站变身移动应用

网页封装APP&#xff1a;让您的网站变身移动应用 随着移动设备的普及&#xff0c;越来越多的人开始使用移动设备浏览网站。但是&#xff0c;传统的网站设计并不适合移动设备的屏幕尺寸和交互方式&#xff0c;这导致了用户体验不佳和流失。 有没有办法让您的网站变身移动应用&…

qt 如果把像素点数据变成一个图片

1.概要 图像的本质是什么&#xff0c;就是一个个的像素点&#xff0c;对与显示器来说就是一个二维数组。无论多复杂的图片&#xff0c;对于显示器来说就是一个二维数组。 2.代码 #include "widget.h"#include <QApplication> #include <QImage> #incl…

HNU电子测试平台与工具2_《计算机串口使用与测量》

&#xff08;这个有留word哈哈&#xff09; 4.1 4.2 Linux 操作系统平台 一、实验目的 了解 Linux 系统文件系统的基本组织了解 Linux 基本的多用户权限系统熟练使用 ls、cd、cat、more、sudo、gcc、vim 等基本命令会使用 ls 和 chmod 命令查看和修改文件权限 二、实…

html+css+js图片手动轮播

源代码在界面图片后面 轮播演示用的几张图片是Bing上的&#xff0c;直接用的几张图片的URL&#xff0c;谁加载可能需要等一下&#xff0c;现实中替换成自己的图片即可 关注一下点个赞吧&#x1f604; 谢谢大佬 界面图片 源代码 <!DOCTYPE html> <html lang&quo…

为什么需要优化Java应用的性能与稳定性?

为什么需要优化Java应用的性能与稳定性&#xff1f; 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们将深入探讨如何优化Java应用的性能与稳定性。在当今…

昇思训练营打卡第十八天(K近邻算法实现红酒聚类)

K近邻&#xff08;K-Nearest Neighbors&#xff0c;KNN&#xff09;算法是一种基本的机器学习算法&#xff0c;它既可以用于分类任务&#xff0c;也可以用于回归任务。KNN算法的核心思想是&#xff0c;如果一个新样本在特征空间中的K个最邻近的样本大多数属于某一个类别&#x…