2019 icpc上海邀請賽 L. Digit sum(找規律)

給一個十進制的數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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章