zoukankan      html  css  js  c++  java
  • Gym

    Gym - 101982D Count The Bits

    传送门

    题意

    给定k和b,问([0,2^n-1])范围内的所有k的倍数转化为二进制后,总共有多少个1。

    题解

    维护两个数组(yu[x]和sum[x])(yu[x])表示在当前这一位之前,有多少个数%k==x,(sum[x])代表在当前这一位之前,那些%k == x的数总共有多少个1。

    从低位到高位递推,假设当前已经走到第 (i) 位上,前 (i-1) 位的(yu)数组和(sum)数组都已经维护好了,前(i-1)位的答案也都计算好了,一起放在ans里,现在考虑如何计算当前这一位可能新增的答案。

    首先考虑当前这一位放0,想象如果给定一个数的二进制形式,在他的最高位前面添一个0,不会改变这个数的大小,所以这一位为0不会对答案产生贡献。

    接下来考虑当前这一位放1,如果在这一位上1那么之前形成的数=之前形成的数们+((1<<i))。因为当前处于第 i 位,所以这一位放1是加上(2^i),也就是((1<<i))。

    因此,我先算出((1<<i)%k=m),然后想要知道加了这一位之后能新产生多少个k的倍数呢,答案就是(yu[k-m])个,因为我当前位置的增量%k=m,那只需要和之前产生的数中%k==k-m的数组合就能得到新的k的倍数。再考虑如何计算这些新产生的k的倍数总共有多少个1呢?

    这样考虑,这些新产生的k的倍数都是由两部分组成的,一部分是当前位上的1,另一部分是前(i-1)位里那些%k==k-m的数的1的总数,是不是觉得这个描述特别熟悉,这就是sum数组的定义啦,那第一部分就是有多少个%k == k-m的数,就会加上多少个1啦。

    因此更新答案就是(ans+=yu[(k-m)\% k ]+ sum[(k-m)\% k])

    维护答案考虑完了,接下来考虑一下怎么把当前这一位置1带来的影响更新到yu数组和sum数组上。

    对于每一个(iin[0,k))

    都有(yu[(i+m)\%k]+=yu[i];)(sum[(i+m)\%k]+=sum[i]+yu[i])

    因为原来%k==i,现在在当前位加了1,相当于加上了一个%k ==m的数。

    sum的增加和之前计算答案那里同理。

    大概就是这样,bshd

    注意点

    个人觉得,此题样例真的非常善良,因为它给了k为1的样例,k=1的话就会要考虑很多地方要格外注意取模,这些取模可能是你考虑其他k的时候觉得没必要的,但是在k=1的时候就显得非常重要,所以如果他不给k=1的样例,那非常有可能你样例都过了然后一直wa一直wa百思不得其解然后自闭~

    乱7788糟

    其实我也分不清这个想法是dp还是递推,有大佬知道的话望为我指点一下迷津,本蒟蒻不胜感激!

    代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=1e3+10;
    const ll mod=1e9+9;
    int yu[maxn],sum[maxn],t1[maxn],t2[maxn];
    int main(){
    	int k,b;scanf("%d%d",&k,&b);
    	yu[0]=1;ll ans=0;
    	for(int i=1;i<=b;i++)
    	{
    		int tt=1;
    		for(int j=1;j<i;j++){
    			tt=(tt*2)%k;
    		}
    		tt%=k;
    		ans=((ans+sum[(k-tt)%k])%mod+yu[(k-tt)%k])%mod;
    		for(int i=0;i<k;i++){
    			t2[(i+tt)%k]=((sum[i]+yu[i])%mod+sum[(i+tt)%k])%mod;
    			t1[(i+tt)%k]=(yu[i]+yu[(i+tt)%k])%mod;
    		}
    		for(int i=0;i<k;i++){yu[i]=t1[i];sum[i]=t2[i];}
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    Web 前端开发中一些兼容性问题及其解决办法 (持续更)
    沈逸的IT专栏---shenyisyn
    程序员该做的事
    职场需要切忌的几点——《程序员,你伤不起》
    百度天气API接口
    C#简单音乐播放器ListBox歌单列表
    CentOS7 安装java(jre 1.8)
    CentOS7 系统安装与设置
    这个可以有,记录下
    在centos 7中让网卡自启动
  • 原文地址:https://www.cnblogs.com/wuanran/p/13567326.html
Copyright © 2011-2022 走看看