【数位DP】Codeforces Gym 100418J Lucky tickets

题意:

设性质P:一个数能够整除它二进制表示下的1的个数。求[1,N]中满足性质P的数的个数。N<=1019。

思路:

数位DP。首先这个数最多有64位,我们可以枚举1的个数x,然后求可以整除x的数的个数。设dp[i][j][k][w]表示从最高位枚举到i位,现在已经构成的数模x余多少(这里是关键,只用考虑余数),现在已经用了k个1,w=0表示现在枚举的这个数已经小于N了,w=1表示从最高位到第i位都与N相同(数位dp计算时的方法:如果当前枚举的数小于N了,那么枚举的这一位就可以任意,如果等于N,那么枚举的这位只能枚举小于原来N这一位的数)。

转移:

    dp[i][j][k][w]+=dp[i-1][(j+1<<i)%x][k+1][neww];(如果能放1)
    dp[i][j][k][w]+=dp[i-1][j][k][neww](放0)
    w=1&&能放1&&放了0->neww=0,w=0->neww=0

代码:

         /* Author: happywu
         *  File: j.cpp
         *  Create Date: 2015-08-07
         */
        #include<cstdio>
        #include<iostream>
        #include<cstring>
        #include<cmath>
        #include<algorithm>
        #include<queue>
        #include<vector>
        #include<cstdlib>
        #include<time.h>
        #include<map>
        #include<set>
        #include<bitset>
        using namespace std;
        typedef long long LL;
        typedef unsigned long long  ULL;
        int b[65],length,MaxBit;
        ULL n,f[65][65][65][2];
        void pre(ULL n){
            int sum=0;
            memset(b,0,sizeof(b));length=0;
            while(n){
                if(n&1){b[sum]=1;length=sum;}
                n>>=1;
                sum++;
            }
        }
        LL dfs(int x,int y,int z,int w){
            if(x==-1){
                if(y==0&&z==MaxBit)return 1;
                else return 0;
            }
            if(f[x][y][z][w]!=-1)return f[x][y][z][w];
            LL ans=0;
            int maxb = w?b[x]:1;
            for(int i=0;i<=maxb;i++){
                if(i)ans+=dfs(x-1,(int)(((ULL)y+(1ULL<<x))%MaxBit),z+1,w);
                else {
                    int flag=1;
                    if(w==1&&maxb)flag=0;
                    if(w==0)flag=0;
                    ans+=dfs(x-1,y,z,flag);
                }
            }
            f[x][y][z][w]=ans;
            return ans;
        }
        int main(int argc, char* argv[]){
            cin>>n;
            pre(n);
            LL ans=0;
            for(int i=1;i<=length+1;i++){
                memset(f,-1,sizeof(f));
                MaxBit = i;
                ans+=dfs(length,0,0,1);
            }
            cout<<ans<<endl;
            return 0;
        }

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-03 03:58:41

【数位DP】Codeforces Gym 100418J Lucky tickets的相关文章

Gym 100418J Lucky tickets(数位dp)

题意:给定一个n,求区间[1, n]之间的所有的a的个数,a满足: a能整除  把a表示自身二进制以后1的个数 思路:题意很绕.... 数位dp,对于所有可能的1的个数我们都dfs一次 对于某一个可能的1的个数p来说,状态dp(len, i, j, k)里的每一位分别表示当前位,当前确定位的值模除p,已经有了多少个1,是否已经小于给定的n, 注意的是这题范围很大,要用unsigned long long 来定义n #include<cstdio> #include<cstring>

DP+高精度 URAL 1036 Lucky Tickets

题目传送门 1 /* 2 题意:转换就是求n位数字,总和为s/2的方案数 3 DP+高精度:状态转移方程:dp[cur^1][k+j] = dp[cur^1][k+j] + dp[cur][k]; 4 高精度直接拿JayYe的:) 5 异或运算的规则: 6 0⊕0=0,0⊕1=1 7 1⊕0=1,1⊕1=0 8 口诀:相同取0,相异取1 9 */ 10 #include <cstdio> 11 #include <cstring> 12 #include <string>

@codeforces - [email&#160;protected] Lucky Tickets

目录 @[email protected] @[email protected] @accepted [email protected] @[email protected] @[email protected] 已知一个数(允许前导零)有 n 位(n 为偶数),并知道组成这个数的数字集合(并不一定要把集合内的数用完).求有多少种可能,使得这个数前半部分的数位和等于后半部分的数位和. 模 998244353. input 第一行两个整数:n k.表示这个数的位数以及组成这个数的数字集合大小.2

codeforces Hill Number 数位dp

http://www.codeforces.com/gym/100827/attachments Hill Number Time Limits:  5000 MS   Memory Limits:  200000 KB 64-bit interger IO format:  %lld   Java class name:  Main Description A Hill Number is a number whose digits possibly rise and then possibl

[Codeforces 258B &amp; 259 D]Little Elephant and Elections 数位dp+dfs

http://codeforces.com/problemset/problem/258/B 题目大意: 说七个party选择数字(各不相同) 而规定的小象的party选择的数字之中所拥有的数字4和7的个数要比其他六个party拥有的个数之和还要严格多,询问方案数. 如m=7时其余的随意选择至少会拥有一个4或7,与题意矛盾,故方案数为0 m=8时,7 1 2 3 5 6 8是一种合法方案 思路: 由于小象的party选到的数字所含4和7的个数至多和m的位数一样多,则枚举小象的party所含4和7

Codeforces 55D (数位DP+离散化+数论)

题目链接: http://poj.org/problem?id=2117 题目大意:统计一个范围内数的个数,要求该数能被各位上的数整除.范围2^64. 解题思路: 一开始SB地开了10维数组记录情况. 首先要求能被各位上的数整除,可以转化为被一个数整除问题. 这个数就是各位上数的最小公倍数LCM(不是GCD). 其次,处理整除问题,得转化成数位DP的余数模板.1~9的LCM最大是2520, 那么%2520,让其可以开数组进行记忆化搜索. 最后, 对于不能%2520最后结果,再%各个数位累计过来的

CodeForces 258B Little Elephant and Elections 数位DP

前面先用数位DP预处理,然后暴力计算组合方式即可. #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #include <cstdlib> #include

CodeForces 55D Beautiful numbers(数位dp+数学)

题目链接:http://codeforces.com/problemset/problem/55/D 题意:一个美丽数就是可以被它的每一位的数字整除的数. 给定一个区间,求美丽数的个数. 显然这是一道数位dp,就是满足一个数能被所有位数的lcm整除即可. 一般都会设dp[len][mod][LCM],mod表示余数,LCM表示前len位的lcm. 但是如果直接裸mod会很复杂,于是再想lcm{0,1,2,3,4,5,6,7,8,9}=2520; 而且lcm{a,b,c,d....}{a,b,c,

数位dp专题 (HDU 4352 3652 3709 4507 CodeForces 55D POJ 3252)

数位dp核心在于状态描述,因为阶段很简单. 一般都是求有多少个数,当然也有求平方的变态题. 因为比这个数小的范围定然是从左至右开始小的,那么什么样的前缀对后面子数有相同的结果? HDU 3652 题意:求能被13整除且含有13这样数的个数. 赤裸裸的两个条件,加上个pre标明下前缀,其实直接开状态也是一样的.整除这个条件可以用余数来表示.余数转移:(mod*10+i)%13 /* *********************************************** Author :bi