https://codeforces.com/contest/1247/problem/C
p为减的常数,
我们可以把题目转化成,求n-k×p里的二进制数为一的数目ans,当ans小于k时。(想想,k是题目要求的结果,数目ans上的位可以变成下一位的二个。所以当ans小于k时其实是满足题目要求的,前提是n-k×p大于k才能变(因为每次至少为1,k次至少为k)
#include <stdio.h>
int solve(int x) //求出x在二进制下有多少个1,即至少需要多少个2^xi次方组成
{
int cnt=0;
while(x)
{
x-=x&(-x);
cnt++;
}
return cnt;
}
int main()
{
int n,p,k=1;
scanf("%d%d",&n,&p);
while(n-k*p>0)
{
if(solve(n-k*p)<=k) //k表示我们提供的次数
{
if(n-k*p>=k) //k表示最少减去的值
{
printf("%d",k);
return 0;
}
}
k++;
}
printf("-1");
}
https://cometoj.com/contest/79/problem/D?problem_id=4219
我们要把这个组合的数化成 u+k=Σa^xi 所以111111 可以化成 999999 即 10 ^ xi次方-1
所以u=9*v,3->27 答案也还是3
#include <stdio.h>
#include <string.h>
char s[1000010];
void solve()
{
int n=strlen(s+1),cnt=0; //cnt为每个位相加
for(int i=n;i;i--)s[i]=(s[i]-'0')*9;
for(int i=n;i;i--)
{
s[i-1]+=s[i]/10;
s[i]%=10;
cnt+=s[i];
}
cnt+=s[0];
int x=10-s[n]; //x必须使s为10的倍数
s[n]+=x;
cnt+=x; //因为位数+x
while(1)
{
for(int i=n;i;i--)
{
if(s[i]>=10) //进位
{
cnt-=9;
s[i-1]++;
s[i]-=10;
}
else break;
}
if(cnt<=x) //满足题意,其实还有个条件 s+x>=x*10只不过根据x递增所以不用判断
{
printf("%d\n",x);
return ;
}
x+=10; //x最少+10,要保证s+x为10的倍数
cnt+=10; //s+10,所以cnt+10
s[n]+=10;
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%s",s+1);
s[0]=0;
solve();
}
}