您的位置:首页 > 其它

Codeforces 914C - Travelling Salesman and Special Numbers 【思维】

2018-03-16 16:13 633 查看
C. Travelling Salesman and Special Numbers
time limit per test 
1 second
memory limit per test     
256 megabytes

The Travelling Salesman spends a lot of time travelling so he tends to get bored. To passtime, he likes to perform
operations on numbers. One such operation is to takea positive integer x
and reduce itto the number of bits set to 1
in the binaryrepresentation of x.
For examplefor number 13
it's true that 1310 = 11012,
so it has 3
bits set and 13
will be reduced to 3
in oneoperation.

He calls anumber
special
if the minimum number of operations to reduce it to 1
is k.

He wants to findout how many special numbers exist which are not greater than
n.
Please help the Travelling Salesman, as he is about to reach hisdestination!

Since the answercan be large, output it modulo
109 + 7.
Input

The first linecontains integer
n
(1 ≤ n < 21000).

The second linecontains integer
k
(0 ≤ k ≤ 1000).

Note that
n
is given in its binary representation without any leading zeros.
Output
Output a single integer — thenumber of special
numbers not greater than n,
modulo 109 + 7.
Examples
Input

110

2
Output

3
Input

111111011

2
Output

169
Note
In the first sample, the three specialnumbers
are 3,
5
and 6.
They get reducedto 2
in one operation (since there are twoset bits in each of 3,
5
and 6)
and then to 1
in one more operation (since there is only one set bit in 2).

【题意】

给出一个数N(N<21000),问有多少不超过它的数,满足在K次操作后刚好变为1。

每次操作能把一个数变为它的二进制表示中1的个数。

【思路】

容易知道,这个数哪怕取到上界,用一次操作一定可以把它变为1000以内的数,那么我们先暴力算出1~1000的数需要几次操作后变为1,记为dp[i].

然后用字符串读入这个数,从第一位开始枚举,如果第i位是1,先统计出前面1的个数num,然后枚举dp[j]==k-1,表示构造的数有j个1,因为不能超过N,我们只要把当前位用0填,然后剩下的len-i-1个位置填j-num个1,用组合数计算即可。

 
#include <cstdio>
#include <bits/stdc++.h>
#include <cmath>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
#define mst(a,b) memset((a),(b),sizeof(a))
#define rush() int T;scanf("%d",&T);while(T--)

typedef long long ll;
const int maxn = 1005;
const ll mod = 1e9+7;
const ll INF = 1e18;
const double eps = 1e-6;

ll fac[maxn];
ll inv[maxn];
int dp[maxn];
char s[maxn];

ll fast_mod(ll a,ll n,ll Mod)
{
ll ans=1;
a%=Mod;
while(n)
{
if(n&1) ans=(ans*a)%Mod;
a=(a*a)%Mod;
n>>=1;
}
return ans;
}

void init()
{
fac[0]=1;
for(int i=1;i<maxn;i++)
{
fac[i]=(fac[i-1]*i)%mod;
}
inv[maxn-1]=fast_mod(fac[maxn-1],mod-2,mod);
for(int i=maxn-2;i>=0;i--)
{
inv[i]=(inv[i+1]*(i+1))%mod;
}
}

ll C(int n,int m)
{
if(n<m) return 0;
return fac
*inv[m]%mod*inv[n-m]%mod;
}

int main()
{
init();
int k;
scanf("%s%d",s,&k);
if(k==0) return puts("1"),0;
for(int i=2;i<maxn;i++) dp[i]=dp[__builtin_popcount(i)]+1;
int len=strlen(s);
int num=0;
ll ans=0;
for(int i=0;i<len;i++)
{
if(s[i]=='0') continue;
for(int j=max(num,1);j<len;j++)
{
if(dp[j]==k-1) ans=(ans+C(len-1-i,j-num))%mod; //当前位放0
}
num++;
}
if(k==1) ans=(ans-1+mod)%mod; //1不在答案里
if(dp[num]==k-1) ans=(ans+1)%mod; //上面的情况都是考虑当前位为0,没有考虑最后一位为1
printf("%lld\n",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息