Soratosorato

ARC182B |{floor(A_i/2^k)}| 题解

Sorato·2024-08-13 09:14·32 次阅读

ARC182B |{floor(A_i/2^k)}| 题解

ARC182B |{floor(A_i/2^k)}| 题解

题目大意#

定义一个长度为 N 的序列 A 的分数为 能被表示成 Ai2k 的数的个数,其中 i=1,2,,Nk 为任意自然数。

给定 N,K,求长度为 N 且元素大小都在 2K1 内的所有序列的分数的最大值,输出任意拥有最大分数的序列。

Solve#

除以 k 下取整相当于二进制下右移 k 位,所以按位考虑。

显然有效位数越多越好,因为有效位数多的右移 k 位得到的数也更多。比如 (101010)2 右移得到的数是包含 (01010)2 能得到的数的。

所以序列中的数二进制下第 K1 位一定是 1,接下来我们考虑怎么构造能使右移得到的不同的数更多。这里有一种构造方法:

Copy
1 0 0 0 ... 1 1 0 0 ... 1 0 1 0 ... 1 1 1 0 ... 1 0 0 1 ... 1 1 0 1 ... 1 0 1 1 ... 1 1 1 1 ... 1 0 0 0 ... 1 1 0 0 ... 1 0 1 0 ... 1 1 1 0 ... ...

即二进制位尽量交错着填,保证每一种情况都被考虑,比如第 K4 位上填 0 的数中,第 K2,K3 位上填 10 的所有 4 种情况都被考虑到。

如此,我们能保证右移任意 k 位得到的数的个数都是卡满的。

Code#

Copy
#include<bits/stdc++.h> using namespace std; inline int read() { short f=1; int x=0; char c=getchar(); while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();} while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } const int N=1e5+10; int T,n,m,a[N]; signed main() { T=read(); while(T--) { n=read();m=read(); for(int i=1;i<=n;i=-~i) a[i]=1<<m-1; for(int i=m-2;i>=0;i--) { bool f=0; for(int j=1;j<=n;j+=(1<<m-2-i),f^=1) for(int k=j;k<=min(j+(1<<m-2-i)-1,n);k=-~k) a[k]+=f<<i; } for(int i=1;i<=n;i=-~i) printf("%d ",a[i]); putchar('\n'); } return 0; }
posted @   Sorato  阅读(32)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
点击右上角即可分享
微信分享提示
目录