BZOJ 3209 二进制数位DP

Description

背景
众所周知,花神多年来凭借无边的神力狂虐各大 OJ、OI、CF、TC …… 当然也包括 CH 啦。
描述
话说花神这天又来讲课了。课后照例有超级难的神题啦…… 我等蒟蒻又遭殃了。
花神的题目是这样的
设 sum(i) 表示 i 的二进制表示中 1 的个数。给出一个正整数 N ,花神要问你
派(Sum(i)),也就是 sum(1)—sum(N) 的乘积。

Input

一个正整数 N。

Output

一个数,答案模 10000007 的值。

Sample Input
样例输入一

3

Sample Output
样例输出一

2

HINT

对于样例一,1*1*2=2;

数据范围与约定

对于 100% 的数据,N≤10^15

解法:

直接暴力做肯定是TLE的,考虑数位DP,数位DP可以解决的问题描述是满足某个条件的数是多少个?这里我

们暴力枚举二进制表示中拥有k个1的数有多少个?根据乘法原理,答案就是这些答案的乘积,暴力乘答案可能

TLE,所以用快速幂乘答案。

///BZOJ 3209

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod=10000007;
LL n;
LL dp[60][60]; //dp[pos][state]第pos位状态有state1的数的个数
LL digit[60];
LL dfs(int pos, int state, bool limit)
{
    if(state>pos) return 0;
    if(pos==0&&state==0) return 1;
    if(pos==0) return 0;
    if(!limit&&dp[pos][state]!=-1) return dp[pos][state];
    int up = limit?digit[pos]:1;
    LL ans = 0;
    for(int i=0; i<=up; i++){
        if(i==1) ans+=dfs(pos-1, state-1, limit&&i==digit[pos]);
        else ans+=dfs(pos-1, state, limit&&i==digit[pos]);
    }
    if(!limit) dp[pos][state]=ans;
    return ans;
}
LL powmod(LL a, LL b){
    LL res=1;
    while(b){
        if(b&1) res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return res;
}
void work(){
    memset(dp, -1, sizeof(dp));
    int pos=0;
    while(n){
        digit[++pos]=n%2;
        n/=2;
    }
    LL ans=1, k;
    for(int i=1; i<=pos; i++){
        k=dfs(pos,i,1);
        if(k){
            ans=ans*powmod(i,k)%mod;
        }
    }
    printf("%lld\n", ans);
}
int main(){
    scanf("%lld",&n);
    work();
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 以下是用 VHDL 语言实现任务方式找出最低位为1的数据的代码: ``` entity find_lowest_bit is port ( data_in : in std_logic_vector(31 downto 0); found_bit_pos : out integer range 0 to 31; clk : in std_logic; reset : in std_logic ); end entity; architecture Behavioral of find_lowest_bit is task search_lowest_bit_pos is variable bit_pos : integer range 0 to 31; begin for i in data_in'range loop if data_in(i) = '1' then bit_pos := i; exit; end if; end loop; found_bit_pos <= bit_pos; end task; begin process(clk, reset) begin if reset = '1' then found_bit_pos <= 0; elsif rising_edge(clk) then search_lowest_bit_pos; end if; end process; end architecture; ``` 该实体有四个端口,其中 `data_in` 是输入的二进制数据,`found_bit_pos` 是输出最低位为1的数据的位置,`clk` 是时钟信号,`reset` 是复位信号。在 `search_lowest_bit_pos` 任务中,使用一个变量 `bit_pos` 来记录最低位为1的数据的位置。在 `process` 进程中,当复位信号为高电平时,输出位置信号 `found_bit_pos` 被清零。当时钟信号上升沿到来时,调用 `search_lowest_bit_pos` 任务来搜索最低位为1的数据的位置,并将结果赋值给 `found_bit_pos` 输出端口。 ### 回答2: VHDL(Very High Speed Integrated Circuit Hardware Description Language)是一种硬件描述语言,可以用于设计和实现数字电路。在VHDL中,我们可以使用任务(process)的方式来实现在一串二进制数据中找出最低位为1的数据。 任务是VHDL中一种并发结构,可以实现并行的功能。在这个任务中,我们可以使用循环语句(for loop)来遍历输入的二进制数据,并通过逐位检查找出最低位为1的数据。 下面是一个示例代码: ```vhdl entity FindLowestBitOne is generic( DATA_WIDTH: integer := 8 ); port( data_in: in std_logic_vector(DATA_WIDTH - 1 downto 0); data_out: out std_logic_vector(DATA_WIDTH - 1 downto 0) ); end entity FindLowestBitOne; architecture Behavioral of FindLowestBitOne is begin process(data_in) variable lowest_bit_index: integer := -1; -- 初始化为-1,表示未找到最低位为1的数据 begin -- 循环遍历输入的二进制数据 for i in DATA_WIDTH - 1 downto 0 loop if data_in(i) = '1' then -- 如果该位为1 lowest_bit_index := i; -- 更新最低位为1的数据的索引 exit; -- 退出循环,找到最低位为1的数据后不再继续遍历 end if; end loop; -- 更新输出数据 if lowest_bit_index >= 0 then -- 如果找到了最低位为1的数据 data_out <= data_in(lowest_bit_index downto 0); -- 输出最低位为1的数据及其后面所有位 else data_out <= (others => '0'); -- 如果未找到最低位为1的数据,则输出全0数据 end if; end process; end architecture Behavioral; ``` 这个代码定义了一个名为FindLowestBitOne的实体和架构,在架构中使用了一个进程(process)来实现找出最低位为1的数据的功能。该进程接收输入数据`data_in`,并根据输入数据中的最低位为1的数据更新输出数据`data_out`。如果未找到最低位为1的数据,则输出全0数据。 以上代码仅是一个示例,具体的实现方式还可以根据实际需求进行调整和改进。 ### 回答3: VHDL是一种硬件描述语言,可以用于设计和实现数字电路。在VHDL中使用任务的方式,可以实现在一串二进制数据中找出最低位为1的数据。 任务(task)是VHDL中一种可以并发执行的子程序,用于完成特定的功能。下面是用任务方式实现在一串二进制数据中找出最低位为1的数据的示例代码: ```vhdl -- 定义任务 task findLowestOneBitData is input signal data : in std_logic_vector; output signal result : out std_logic_vector; begin for i in data'range loop if data(i) = '1' then result <= data(i downto 0); exit; -- 找到最低位为1的数据后退出循环 end if; end loop; end task; -- 实例化任务 signal data : std_logic_vector(7 downto 0) := "11010100"; signal result : std_logic_vector(7 downto 0); begin -- 调用任务 findLowestOneBitData(data, result); -- 输出结果 report "最低位为1的数据为: " & to_string(result); end architecture; ``` 在上述代码中,我们定义了一个名为`findLowestOneBitData`的任务,该任务接受一个输入参数`data`表示二进制数据,同时也有一个输出参数`result`表示找到的最低位为1的数据。任务通过遍历`data`中的每个位,找到最低位为1时,将从最低位到该位的数据赋值给`result`,然后退出循环。 在主体部分,我们实例化了任务,并传递了输入数据`data`和输出数据`result`。之后,通过输出语句`report`打印出找到的最低位为1的数据。 需要注意的是,上述代码只是一个简单示例,具体的实现方式可能因实际需求而有所不同。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值