k个不同i的a次方-一个常数相加 等于一个数

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();
    }
}
发布了88 篇原创文章 · 获赞 8 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_44879687/article/details/103302862