2019 icpc上海邀请赛 L. Digit sum(找规律)

2 篇文章 0 订阅

给一个十进制的数n,把他转换成b进制,求从1到这个数n在b进制下每个数的每位数之和的总和。
题解给的暴力打表就行了。
我的解法就是找规律,大概就是先求n/b,这样就知道n的个位数出现了几轮,乘上1到9之和再乘上每个个位数出现的次数1,继续算剩下的没有出现完成一轮的个位数之和,顺便再加上十位,百位。。上的数字之和,还要乘上那个出现次数1,然后n/=b,并且n–(这里的n在个位数算过,所以删掉一),出现次数*b,就相当于把原来的十位数当个位数了。仔细想想还是不难的,随便交一发就过了也不知道自己推错没有,不过时间确实只有打表的十分之一。

#include <bits/stdc++.h>
#define eps 1e-14
#define pi acos(-1)
#define ll long long
#define RD T*(rand()*2-RAND_MAX)
#define Drand (long double)rand()/RAND_MAX
#define LINF 0x7f7f7f7f7f7f7f7f
#define INF 0x3f3f3f3f
using namespace std;
const int maxn=5e5+50;
const long long mod=1e18;
ll MOD(ll a,ll m){return a>m?a%m+m:a;}
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}

int n;
int b;

int cal()
{
    int dif=10;
    int c=1;
    int ans=0;
    int add=(b-1)*b/2;
//    cout<<add<<endl;
    while(n>0){
        int ten=n/b;
//        cout<<"ten = "<<ten<<endl;
        if(ten>=0){
            ans+=add*ten*c;
        }
        int ge=n%b;
//        cout<<"ge = "<<ge<<endl;
        ans+=(1+ge)*(ge)/2*c;
        int pp=ten,ansp=0;
        while(pp>0){
            ansp+=pp%b;
            pp/=b;
        }
        ans+=ansp*(ge+1)*c;
//        cout<<"ans = "<<ans<<endl;
        n/=b;
        n--;
        c*=b;
    }
    return ans;
}

int main()
{
//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
    int t;
    scanf("%d",&t);
    int cas=1;
    while(t--){
        scanf("%d",&n);
        scanf("%d",&b);
        printf("Case #%d: %d\n",cas++,cal());
    }
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值