洛谷题目传送门

ATcoder题目链接

题目大意

给你正整数 \(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的更多相关文章

  1. [LeetCode 题解]:Path Sum

    前言   [LeetCode 题解]系列传送门:  http://www.cnblogs.com/double-win/category/573499.html   1.题目描述 Given a bi ...

  2. LeetCode题解39.Combination Sum

    39. Combination Sum Given a set of candidate numbers (C) (without duplicates) and a target number (T ...

  3. PAT甲题题解-1081. Rational Sum (20)-模拟分数计算

    模拟计算一些分数的和,结果以带分数的形式输出注意一些细节即可 #include <iostream> #include <cstdio> #include <algori ...

  4. 《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 ...

  5. [题解] 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\ ...

  6. 题解 CF920F 【SUM and REPLACE】

    可以事先打表观察每个数的约数个数,观察到如果进行替换,若干次后这个数便会被替换成1. 所以我们可以直接暴力的进行区间修改,若这个数已经到达1或2,则以后就不再修改,用并查集和树状数组进行维护. 这个方 ...

  7. LeetCode 题解之 Two Sum

    1.题目描述 2.问题分析 使用hashTable 寻找,target  -  num[i] ,将时间复杂度降低到 O(n): 3.代码 vector<int> twoSum(vector ...

  8. LeetCode题解之 two sum 问题

    1.题目描述 2.题目分析 考虑使用hashMap的方式将数组中的每个元素和下表对应存储起来,然后遍历数组,计算target 和 数组中每个元素的差值,在hashMap中寻找,一直到找到最后一对. 3 ...

  9. leetcode个人题解——#39 Combination Sum

    思路:先对数据进行排序(看评论给的测试数据好像都是有序数组了,但题目里没有给出这个条件),然后回溯加剪枝即可. class Solution { public: ; vector<vector& ...

  10. LeetCode题解 #1 Two Sum

    在LeetCode做的第一到题 题目大意:给出n个数,在其中找出和为一个特定数的两个数. Input: numbers={2, 7, 11, 15}, target=9Output: index1=1 ...

随机推荐

  1. Spring纯注解的事务管理

    Spring纯注解的事务管理 源码 代码测试 pom.xml <?xml version="1.0" encoding="UTF-8"?> < ...

  2. Java编程--接口(interface)简单用法(一)

    接口是Java中的一个重要的概念. interface:定义了子类要实现的功能.由全局常量和抽象方法组成. 接口的定义 定义一个简单的interface public interface A {  p ...

  3. 《原型设计工具深度解析:Axure到墨刀的实战指南》

    原型设计工具深度解析:从Axure到墨刀的实战应用 项目背景 "Shou学"作为信息学院本科必修课指南平台,需通过高保真原型实现课程导航.知识点拆解.习题模拟等核心功能.本文结合& ...

  4. java处理http请求之Apache httpClient入门教程

    说明 本文示例代码基于 4.5.13 版本 转载请注明出处:https://www.cnblogs.com/qnlcy/p/15378446.html 一.项目介绍 Apache 提供用来做http请 ...

  5. windows11 安装WSL2详细过程

    一.什么是 WSL 2 时间来到 2017 年,事情正在起变化.微软正式发布了「适用于 Linux 的 Windows 子系统」,即人们熟知的 Windows Subsystem for Linux, ...

  6. HarmonyOS NEXT实战教程:菜谱App

    随着鸿蒙系统5.0的发布,兼容的机型越来越多,对于开发者来说机会也越来越多,大家不要气馁,学习鸿蒙肯定会有用武之地,我们要做的就是做好准备. 今天跟大家分享实战教程是一个菜谱App.   ListO& ...

  7. Pycomcad实现Autocad橡皮线效果

    import sys sys.path.append(r'F:\PycharmProject\PycomCAD') from pycomcad import * def tryit(): acad.I ...

  8. 第二次blog作业

    1.前言 这是第二次接触 Java 编程语言大题.相比第一次的电梯调度问题,这次面对航空货运管理系统时我不再迷茫.反复读题后,我很快确定了代码编辑方向,并一步步完成代码编写.航空货运管理系统难度不大但 ...

  9. 【2020.11.25提高组模拟】太空漫步(walking) 题解

    [2020.11.25提高组模拟]太空漫步(walking) 题解 题目描述 Do not go gentle into that good night. Old age should burn an ...

  10. Linux服务器(CentOS/Ubuntu)接口Bond模式详解、配置指南及交换机对应接口的配置示例

    以下是关于Linux服务器(CentOS/Ubuntu)与交换机对接的接口Bond模式详解.配置指南及交换机配置示例(思科/华为/华三) 的全面说明: 一.Linux Bonding 模式对比 模式 ...