CF914C Travelling Salesman and Special Numbers

题目描述

对于一个正整数x,我们定义一次操作是将其变为它二进制下“1”的个数,比如我们知道1310?=11012 ,而1101有三个"1",所以对13进行一次操作就会将其变为3。显而易见的是,对于一个正整数,我们在进行若干次操作后,一定会将其变为1。

给定n和k,其中n是在二进制下被给出,求出所有不大于n且将其变为1的最小操作次数为k的数的个数对10^9+7取模的结果。

1<=n<21000, 0<=k<=10000

题解

因为n在二进制下长度最大为1000,所以最多有1000个1,所以转化一次最多是1000。

我们可以处理出当前数为x时还需要几步到1,cnt[i]=cnt[sum[i]]+1,sum[i]为i在二进制下有多少个1,sum[i]=sum[i^lowbit(i)]+1,i^lowbit(i)就是i在二进制下去掉最右边的1,这个数一定先处理出来了,所以就可以递推,x在1000以内。

然后就可以进行数位DP,f[s][num][lim]表示当前处理到第i位,1的个数为num

那么最后cnt[num]+1==k就是一种,num就是枚举出的数转换一次得到的。

然后就WA了....

考虑k=0时,会输出0,但是容易发现1就是一个解,这是因为cnt是操作了一次之后,而1不需要操作,所以特判k=0即可。

k=1时,答案会多2,这是因为0和1的关系,所以把cnt[0]设成负数,然后特判k=1时答案-1即可。

#include<bits/stdc++.h>
using namespace std;

const int mod=1000000007;
const int maxn=1005;
char s[maxn];
int k,len,num[maxn];
int sum[maxn],cnt[maxn];
int f[maxn][maxn][2];

void init(){
    sum[0]=0;
    cnt[1]=0;
    cnt[0]=-2;
    for(int i=1;i<=1000;i++) sum[i]=sum[i^(i&-i)]+1;
    for(int i=2;i<=1000;i++) cnt[i]=cnt[sum[i]]+1;
}

int dfs(int s,int c,bool lim){
    if(!s) return cnt[c]+1==k;
    if(f[s][c][lim]!=-1) return f[s][c][lim];
    int mx= lim ? num[s] : 1;
    int ret=0;
    for(int i=0;i<=mx;i++)
     ret=(ret+dfs(s-1,c+(i==1),lim&&i==mx))%mod;
    return f[s][c][lim]=ret;
}

int cx(){
    memset(f,-1,sizeof(f));
    return dfs(len,0,true);
}

int main(){
    init();
    scanf("%s%d",s,&k);
    if(!k){printf("1");return 0;}
    len=strlen(s);
    for(int i=1;i<=len;i++) num[i]=s[len-i]-‘0‘;
    int ans=cx();
    if(k==1) ans--;
    printf("%d",ans);
}

网上都是什么组合数,明明就有数位DP的标签(掩饰自己不会组合数)

原文地址:https://www.cnblogs.com/sto324/p/11401958.html

时间: 2024-08-30 16:55:33

CF914C Travelling Salesman and Special Numbers的相关文章

Codeforces 914 C Travelling Salesman and Special Numbers

Discription The Travelling Salesman spends a lot of time travelling so he tends to get bored. To pass time, he likes to perform operations on numbers. One such operation is to take a positive integer x and reduce it to the number of bits set to 1 in

hdu5402 Travelling Salesman Problem(棋盘染色+模拟)

题目: Travelling Salesman Problem Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 906    Accepted Submission(s): 331 Special Judge Problem Description Teacher Mai is in a maze with n rows and m c

HDOJ 5402 Travelling Salesman Problem 模拟

行数或列数为奇数就能够所有走完. 行数和列数都是偶数,能够选择空出一个(x+y)为奇数的点. 假设要空出一个(x+y)为偶数的点,则必须空出其它(x+y)为奇数的点 Travelling Salesman Problem Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 747    Accepted Submission(s): 272

多校9 1007 Travelling Salesman Problem

Travelling Salesman Problem Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 829    Accepted Submission(s): 182Special Judge Problem Description Teacher Mai is in a maze with n rows and m columns

HDU 5402 Travelling Salesman Problem (模拟 有规律)

Travelling Salesman Problem Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 568    Accepted Submission(s): 200 Special Judge Problem Description Teacher Mai is in a maze with n rows and m colum

HDU 5402 Travelling Salesman Problem (构造)(好题)

大致题意:n*m的非负数矩阵,从(1,1) 只能向四面走,一直走到(n,m)为终点,路径的权就是数的和,输出一条权值最大的路径方案 思路:由于这是非负数,要是有负数就是神题了,要是n,m中有一个是奇数,显然可以遍历,要是有一个偶数,可以画图发现,把图染成二分图后,(1,1)为黑色,总能有一种构造方式可以只绕过任何一个白色的点,然后再遍历其他点,而绕过黑色的点必然还要绕过两个白色点才能遍历全部点,这是画图发现的,所以找一个权值最小的白色点绕过就可以了, 题解给出了证明: 如果n,mn,m都为偶数,

构造 - HDU 5402 Travelling Salesman Problem

Travelling Salesman Problem Problem's Link: http://acm.hdu.edu.cn/showproblem.php?pid=5402 Mean: 现有一个n*m的迷宫,每一个格子都有一个非负整数,从迷宫的左上角(1,1)到迷宫的右下角(n,m),并且使得他走过的路径的整数之和最大,问最大和为多少以及他走的路径. analyse: 首先,因为每个格子都是非负整数,而且规定每个格子只能走一次,所以为了使和尽可能大,必定是走的格子数越多越好.这样我们就需

【HDOJ 5402】Travelling Salesman Problem

[HDOJ 5402]Travelling Salesman Problem 一开始以为是搜索 仔细画了画发现就一模拟 奇数行或奇数列的时候怎么走都能全走完 偶数行偶数列的时候就要挑了 . * . * . * * . * . * . . * . * . * * . * . * . 以4*6为例(如上图 星号可以保证不取其中一个可遍历完全图 点好的话就会连带一些星号 所以绕过星号中的最小值 是最佳遍历方式 输入的时候找到最小值并记录下行列 遍历到改行前以 右走到头 下 左走到头 下 右走到头这种方

PAT 甲级 1150 Travelling Salesman Problem

https://pintia.cn/problem-sets/994805342720868352/problems/1038430013544464384 The "travelling salesman problem" asks the following question: "Given a list of cities and the distances between each pair of cities, what is the shortest possib