Comet OJ C1076 [Contest #4]求和

题目
首先咱们能够经过经典容斥转化为计算\([1,x]\)的答案。
如今咱们考虑一个数的个位对答案的贡献。
每作一次操做都会让个位加上十位而后取模,直到只有个位为止。
咱们发现这个过程当中,个位数前的系数永远都是\(1\),也就是个位数对答案的贡献系数为\(1\)
这意味着咱们对于一个固定的只有个位没肯定的数,咱们枚举其个位\(0\sim9\),其答案也是\(0\sim9\),因此咱们能够直接求出\([1,\lfloor\frac n{10}\rfloor*10-1]\)的答案为\(\lfloor\frac n{10}\rfloor*45\)
而后剩下\(n\mod10+1\)个数,直接计算很不优秀。
咱们先暴力计算\(t=f(\lfloor\frac n{10}\rfloor)\),那么\(f(\lfloor\frac n{10}\rfloor)+i=t+i(i\in[0,9])\),这样只用暴力算一次,很是优秀。c++

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int a[19];
int f(ll x)
{
    int len=0,i;
    while(x) a[++len]=x%10,x/=10;
    while(len^1)
    {
    for(i=1;i<len;++i) a[i]=(a[i]+a[i+1])%10;
    for(--len;!a[len]&&len^1;--len);
    }
    return a[len];
}
ll cal(ll x)
{
    if(x<10) return x*(x+1)/2;
    ll s=x/10*45;int o=x%10,i,t=f(x/10*10);
    for(i=0;i<=o;++i) s+=(t+i)%10;
    return s;
}
int main()
{
    int T;ll l,r;
    for(scanf("%d",&T);T;--T) scanf("%lld%lld",&l,&r),printf("%lld\n",cal(r)-cal(l-1));
}
相关文章
相关标签/搜索