HDU 5936 折半枚举法

Difference

kk说是16年CCPC杭州赛的银牌题

给定 x , K ( x < 1 0 9 , 1 ≤ K ≤ 9 ) x,K(x<10^9,1≤K≤9) x,K(x<109,1K9)求满足 x = f ( y , K ) − y x=f(y, K)-y x=f(y,K)y的所有正整数y的数量。
f ( y , K ) = ∑ z  in every digits of  y z K ( f ( 233 , 2 ) = 2 2 + 3 2 + 3 2 = 22 ) f(y, K)=\sum_{z \text { in every digits of } y} z^{K}\left(f(233,2)=2^{2}+3^{2}+3^{2}=22\right) f(y,K)=z in every digits of yzK(f(233,2)=22+32+32=22)

  1. 定y的范围, y < 1 0 10 y<10^{10} y<1010
  2. 由于每个数字对f的贡献独立,所以可以折半求解。令 y = 1 0 5 ∗ a + b y=10^5*a+b y=105a+b,则 x − ( f ( a , K ) − 1 0 5 ∗ a ) = f ( b , K ) − b x-(f(a,K)-10^5*a)=f(b,K)-b x(f(a,K)105a)=f(b,K)b。先求出1e5以内所有的 f ( b , K ) − b f(b,K)-b f(b,K)b,然后进行枚举高5位a, v a l = x − ( f ( a , K ) − 1 0 5 ∗ a ) val=x-(f(a,K)-10^5*a) val=x(f(a,K)105a),二分查找对应的 f ( b , K ) − b f(b,K)-b f(b,K)b的数量。
  3. 注意:当 x = 0 x=0 x=0时,会把0算进去。题目求正整数,减去1。
#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
#define debug(_x) cout<<#_x<<": "<<_x<<endl;
typedef long long ll;
const int maxn=1e5+3,inf=1e9+1e5;
ll f[10][maxn],d[10][maxn];
ll qpow(int x,int k){
    ll res=1;
    while(k){
        if(k&1)res*=x;
        x=x*x;
        k>>=1;
    }
    return res;
}
void init(){
    int e5=100000;
    for(int j=1;j<=9;++j){
        for(int i=1;i<e5;++i){
            f[j][i] = f[j][i/10] + qpow(i%10,j);
            d[j][i] = f[j][i] - i;
        }
        sort(d[j],d[j]+e5);
    }
}
ll solve(int x,int k){
    int ans=0;
    ll val,e5=100000;
    for(int i=0;i<e5;++i){
        val = x - (f[k][i] - e5 * i);
        ans += upper_bound(d[k],d[k]+e5,val)-lower_bound(d[k],d[k]+e5,val);
    }
    return ans;
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    int T,x,k;
    init();
    cin>>T;
    for(int casei=1;casei<=T;++casei){
        cin>>x>>k;
        cout<<"Case #"<<casei<<": "<<solve(x,k)+(x ? 0 : -1)<<endl;
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值