Hdu 5936 Difference【思维+折半枚举+二分】

142 篇文章 0 订阅
111 篇文章 0 订阅

Difference

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 977    Accepted Submission(s): 271


Problem Description
Little Ruins is playing a number game, first he chooses two positive integers  y  and  K  and calculates  f(y,K) , here

f(y,K)=z in every digits of yzK(f(233,2)=22+32+32=22)


then he gets the result

x=f(y,K)y


As Ruins is forgetful, a few seconds later, he only remembers  K x  and forgets  y . please help him find how many  y  satisfy  x=f(y,K)y .
 

Input
First line contains an integer  T , which indicates the number of test cases.

Every test case contains one line with two integers  x K .

Limits
1T100
0x109
1K9
 

Output
For every test case, you should output  'Case #x: y', where  x indicates the case number and counts from  1 and  y is the result.
 

Sample Input
  
  
2 2 2 3 2
 

Sample Output
  
  
Case #1: 1 Case #2: 2

题目大意:


F(y,K)=Σ(y的各个位子上的数)^K;

然后我们可以得到一个值X=F(y,K)-y;

我们现在有一个值X,问有多少个正整数y使得其满足条件。


思路:


①首先观察到X的计算式子,X=F(y,K)-y;根据X的数据范围X>=0我们可以知道,y是不可以大于X的。

所以我们可以简单的认定,y最长可以达到10个长度。


②那么我们可以折半枚举,O(1e5)去枚举前五个长度的部分,O(1e5)去枚举后五个长度的部分。

我们知道,我们将数分成两部分并不影响结果的运算,前五个长度的部分对结果的贡献值为val-y*1e5;后五个长度的贡献值为val-y.

那么我们对应得到后五个长度部分的值之后,我们可以二分前五个长度合法的区间范围个数【L,R】,那么当前结果贡献的值就是R-L+1.


③值得注意的点是,y需要是正整数,y==0的情况不能存在,特判一下即可。


Ac代码:


#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define ll long long int
ll temp[1600000];
ll poww[15][25];
ll X,K,output;
int cnt;
void init()
{
    for(int i=0;i<=9;i++)
    {
        poww[i][0]=1;
        for(int j=1;j<=9;j++)
        {
            poww[i][j]=poww[i][j-1]*i;
        }
    }
}
void dfs(ll y,ll val,int dep)
{
    if(dep==5)
    {
        temp[cnt++]=val-y*100000;
        return ;
    }
    for(int i=0;i<=9;i++)
    {
        dfs(y*10+i,val+poww[i][K],dep+1);
    }
}
void Dfs(ll y,ll val,int dep)
{
    if(dep==5)
    {
        if(y==0)return ;
        int L=-1,R=-1;
        int l=0;
        int r=cnt-1;
        while(r-l>=0)
        {
            int mid=(l+r)/2;
            if(val-y+temp[mid]<X)
            {
                l=mid+1;
            }
            else if(val-y+temp[mid]>=X)
            {
                if(val-y+temp[mid]==X)
                {
                    L=mid;
                }
                r=mid-1;
            }
        }
        l=0;
        r=cnt-1;
        while(r-l>=0)
        {
            int mid=(l+r)/2;
            if(val-y+temp[mid]<=X)
            {
                if(val-y+temp[mid]==X)
                {
                    R=mid;
                }
                l=mid+1;
            }
            else if(val-y+temp[mid]>X)
            {
                r=mid-1;
            }
        }
        if(L==-1||R==-1)return ;
        output+=R-L+1;
        return ;
    }
    for(int i=0;i<=9;i++)
    {
        Dfs(y*10+i,val+poww[i][K],dep+1);
    }
}
int main()
{
    init();
    int kase=0;
    int t;scanf("%d",&t);
    while(t--)
    {
        cnt=0;
        output=0;
        scanf("%lld%lld",&X,&K);
        dfs(0,0,0);
        sort(temp,temp+cnt);
        Dfs(0,0,0);
        printf("Case #%d: ",++kase);
        printf("%lld\n",output);
    }
}













  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值