[题解] AT_ABC406_E Popcount Sum 3
题目大意
给你正整数 \(N\) 和 \(K\)。
求所有不超过 \(N\) 且满足以下条件的正整数 \(x\) 的 和(取模 \(998244353\)):
- \(x\) 的 \(\mathrm{popcount}\) 恰好是 \(K\) 。
给你 \(T\) 个测试用例,请逐个求解。
什么是 \(\mathrm{popcount}\)?
对于正整数 \(y\),\(\mathrm{popcount}(y)\) 表示 \(y\) 的二进制表示中 \(1\) 位的数目。
例如,\(\mathrm{popcount}(5)=2\),\(\mathrm{popcount}(16)=1\),\(\mathrm{popcount}(25)=3\)。
思路
因为题目让我们在一个范围 \(1\sim N\) 中符合条件的数的和,\(N\) 的上界是 \(2^{60}\),是个二进制数,可以拆位。
所以,我们考虑使用数位dp来做。
状态定义
设 \(f_{i,j}\) 表示从高望低数前 \(i\) 位二进制,恰好有 \(j\) 个 \(1\) 的个数。
\(s_{i,j}\) 表示这些数的和。
状态转移:
\(f_{i,j}=f_{i+1,j}+f_{i+1,j+1}\)
\(s_{i,j}=s_{i+1,j}+s_{i+1,j+1}+2^i\times f_{i+1,j+1}\)
解释
\(s_{i+1,j}\) 和 \(s_{i+1,j+1}\) 表示第 \(i\) 位为 \(0/1\) 的数字和。
\(2^i\times s_{i+1,j+1}\) 表示第 \(i\) 位为 \(1\) 的贡献(第 \(i\) 位数 \(\times\) 方案数)。
做法
- 用记忆化搜索进行数位dp。
- 用
pair<int,int>
代表 \(f\) 和 \(s\) 数组。
代码
#include <bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;
const int N = 105;
const int mod = 998244353;
vector<int> bits;
int n, k;
pair<int,int> dp[N][N][2];
int qpow(int a, int b) {
a %= mod;
int ans = 1;
while (b) {
if (b & 1) ans = ans * a % mod;
a = a * a % mod;
b >>= 1;
}
return ans % mod;
}
pair<int, int> dfs(int pos, int cnt, int tag){
//当前处理到pos为,有cnt个1,高位是否存在限制
if(pos == bits.size()){
if(cnt == k) return {1, 0};
else return {0, 1};
}
if(dp[pos][cnt][tag].first != -1){
return dp[pos][cnt][tag];
}
int rcnt = 0, rsum = 0;
int mx = tag? bits[pos] : 1;
for(int d = 0; d <= mx; d++){
if(cnt + d > k) continue;
auto [ncnt, nsum] = dfs(pos + 1, cnt + d, tag & (d == bits[pos]));
if(ncnt == 0) continue;
rcnt += ncnt;
int len = bits.size();
rsum += d * qpow(2, len-1-pos) % mod * ncnt % mod + nsum;
rcnt %= mod;
rsum %= mod;
}
dp[pos][cnt][tag] = {rcnt, rsum};
return dp[pos][cnt][tag];
}
inline void init(){
memset(dp, -1, sizeof(dp));
bits.clear();
return ;
}
void solve(){
init();
cin >> n >> k;
int m = n;
while(m > 0){
bits.push_back(m % 2);
m /= 2;
}
reverse(bits.begin(), bits.end());
if(k > bits.size()) {
cout << 0 << endl;
return ;
}
return cout << dfs(0, 0, 1).second << endl,void();
}
inline int read(){int x;cin>>x;return x;}
signed main(){
cin.tie(0)->sync_with_stdio(0);
int _=read();
while(_--) solve();
return 0;
}
[题解] AT_ABC406_E Popcount Sum 3的更多相关文章
- [LeetCode 题解]:Path Sum
前言 [LeetCode 题解]系列传送门: http://www.cnblogs.com/double-win/category/573499.html 1.题目描述 Given a bi ...
- LeetCode题解39.Combination Sum
39. Combination Sum Given a set of candidate numbers (C) (without duplicates) and a target number (T ...
- PAT甲题题解-1081. Rational Sum (20)-模拟分数计算
模拟计算一些分数的和,结果以带分数的形式输出注意一些细节即可 #include <iostream> #include <cstdio> #include <algori ...
- 《LeetBook》LeetCode题解(1) : Two Sum[E]——哈希Map的应用
001.Two Sum[E] Two SumE 题目 思路 1双重循环 2 排序 3 Hashmap 1.题目 Given an array of integers, return indices o ...
- [题解] CF622F The Sum of the k-th Powers
CF622F The Sum of the k-th Powers 题意:给\(n\)和\(k\),让你求\(\sum\limits_{i = 1} ^ n i^k \ mod \ 10^9 + 7\ ...
- 题解 CF920F 【SUM and REPLACE】
可以事先打表观察每个数的约数个数,观察到如果进行替换,若干次后这个数便会被替换成1. 所以我们可以直接暴力的进行区间修改,若这个数已经到达1或2,则以后就不再修改,用并查集和树状数组进行维护. 这个方 ...
- LeetCode 题解之 Two Sum
1.题目描述 2.问题分析 使用hashTable 寻找,target - num[i] ,将时间复杂度降低到 O(n): 3.代码 vector<int> twoSum(vector ...
- LeetCode题解之 two sum 问题
1.题目描述 2.题目分析 考虑使用hashMap的方式将数组中的每个元素和下表对应存储起来,然后遍历数组,计算target 和 数组中每个元素的差值,在hashMap中寻找,一直到找到最后一对. 3 ...
- leetcode个人题解——#39 Combination Sum
思路:先对数据进行排序(看评论给的测试数据好像都是有序数组了,但题目里没有给出这个条件),然后回溯加剪枝即可. class Solution { public: ; vector<vector& ...
- LeetCode题解 #1 Two Sum
在LeetCode做的第一到题 题目大意:给出n个数,在其中找出和为一个特定数的两个数. Input: numbers={2, 7, 11, 15}, target=9Output: index1=1 ...
随机推荐
- Spring纯注解的事务管理
Spring纯注解的事务管理 源码 代码测试 pom.xml <?xml version="1.0" encoding="UTF-8"?> < ...
- Java编程--接口(interface)简单用法(一)
接口是Java中的一个重要的概念. interface:定义了子类要实现的功能.由全局常量和抽象方法组成. 接口的定义 定义一个简单的interface public interface A { p ...
- 《原型设计工具深度解析:Axure到墨刀的实战指南》
原型设计工具深度解析:从Axure到墨刀的实战应用 项目背景 "Shou学"作为信息学院本科必修课指南平台,需通过高保真原型实现课程导航.知识点拆解.习题模拟等核心功能.本文结合& ...
- java处理http请求之Apache httpClient入门教程
说明 本文示例代码基于 4.5.13 版本 转载请注明出处:https://www.cnblogs.com/qnlcy/p/15378446.html 一.项目介绍 Apache 提供用来做http请 ...
- windows11 安装WSL2详细过程
一.什么是 WSL 2 时间来到 2017 年,事情正在起变化.微软正式发布了「适用于 Linux 的 Windows 子系统」,即人们熟知的 Windows Subsystem for Linux, ...
- HarmonyOS NEXT实战教程:菜谱App
随着鸿蒙系统5.0的发布,兼容的机型越来越多,对于开发者来说机会也越来越多,大家不要气馁,学习鸿蒙肯定会有用武之地,我们要做的就是做好准备. 今天跟大家分享实战教程是一个菜谱App. ListO& ...
- Pycomcad实现Autocad橡皮线效果
import sys sys.path.append(r'F:\PycharmProject\PycomCAD') from pycomcad import * def tryit(): acad.I ...
- 第二次blog作业
1.前言 这是第二次接触 Java 编程语言大题.相比第一次的电梯调度问题,这次面对航空货运管理系统时我不再迷茫.反复读题后,我很快确定了代码编辑方向,并一步步完成代码编写.航空货运管理系统难度不大但 ...
- 【2020.11.25提高组模拟】太空漫步(walking) 题解
[2020.11.25提高组模拟]太空漫步(walking) 题解 题目描述 Do not go gentle into that good night. Old age should burn an ...
- Linux服务器(CentOS/Ubuntu)接口Bond模式详解、配置指南及交换机对应接口的配置示例
以下是关于Linux服务器(CentOS/Ubuntu)与交换机对接的接口Bond模式详解.配置指南及交换机配置示例(思科/华为/华三) 的全面说明: 一.Linux Bonding 模式对比 模式 ...