Book Reading(图书阅读)

180 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。​​​​​​​​​ ​

 Polycarp is reading a book consisting of n pages numbered from 1 to n. Every time he finishes the page with the number divisible by m, he writes down the last digit of this page number. For example, if n=15 and m=5, pages divisible by m are 5,10,15 Their last digits are 5,0,5 correspondingly, their sum is 10.

Your task is to calculate the sum of all digits Polycarp has written down.

You have to answer q independent queries.

Input

The first line of the input contains one integer q(1≤q≤1000) — the number of queries.

The following qq lines contain queries, one per line. Each query is given as two integers n and m (1≤n,m≤1016) — the number of pages in the book and required divisor, respectively.

Output

For each query print the answer for it — the sum of digits written down by Polycarp.

Example

Input

7
1 1
10 1
100 3
1024 14
998244353 1337
123 144
1234312817382646 13

Output

1
45
153
294
3359835
0
427262129093995

 由于阅读能力差,一般看全英稍有难度点的题,都至少读两遍,才大概了解题意,这类题在我眼中就是找规律...(没办法,算法逻辑不强,只能数学找规律来凑表示baobao也很无奈啊~~~),我就是分析几组数据  才总结出来规律开敲代码~

由于数据较大,用unsigned long long数据类型,然后虽然思路清晰,但是代码在实现起来比较繁琐(唠叨~~),所以A了一道题,也不是很开心~~,比赛结束后,又看了网上的大佬们都怎么写的,借鉴借鉴提高提高,嘿嘿,果然没有失望在下面一次呈现~

还有这道题,给我也是有收获的,比如代码中间隐藏的几行注释其实通过每一步的数据输出,不但能发现哪里开始数据出错,也能及时发现题目中隐藏的规律所在(在探索中摸索谁都不曾停下脚步~~O(∩_∩)O哈哈哈

题意:

****在 [1,n] 这个区间内,若存在某个数im的倍数,则把i的个位数加起来进行输出。

方法:(是笨的方法没错了但是也花了我不少功夫,当看到Accepted的时候,还是很欣慰的~~不负有心儿人了啊~)

分别列出能整出m(m个位数可能是0~9) 的数,通过写几个(哈哈,个人喜欢找规律,因为不费脑子嘻嘻),会发现都会出现多少一循环,就是我代码中的aa[ ] 数组,然后写出这个循环所有个位数的和,就是a[ ] 数组,然后计算有多少个这个循环,乘以a[ ] 数组,再加上最后多余的几项(就是不够一个整循环的写的好详细哟,把当时的想法全都回忆出来了...)

AC:

#include<stdio.h>
#include<string.h>
#include<algorithm>
typedef unsigned long long ull;
const int N=1e6+10;
using namespace std;
ull a[20]= {0,45,20,45,20,5,20,45,20,45,0};///每个循环体  个位数之和
ull aa[20]= {0,10,5,10,5,2,5,10,5,10};///几个数构成一个循环体
struct node
{
    ull b0,b1,b2,b3,b4,b5,b6,b7,b8,b9;
} gm[10];
int main()
{
    for(ull i=1; i<=10; i++)
    {
        gm[i].b0=0;
        gm[i].b1=(1*i)%10;
        gm[i].b2=(2*i)%10;
        gm[i].b3=(3*i)%10;
        gm[i].b4=(4*i)%10;
        gm[i].b5=(5*i)%10;
        gm[i].b6=(6*i)%10;
        gm[i].b7=(7*i)%10;
        gm[i].b8=(8*i)%10;
        gm[i].b9=(9*i)%10;
    }
    int q;
    scanf("%d",&q);
    ull n,m;
    while(q--)
    {
        scanf("%llu %llu",&n,&m);
        if(m>n||m%10==0)///起到剪枝的作用
        {
            printf("0\n");
            continue;
        }
        ull x=m%10;///求m的个位
        ull sum=n/m;///在1~n区间内有多少个符合的数
        ull summ=sum/aa[x];///有多少个整循环
        ull ans=sum%aa[x];///最后多余的几项
//        printf("***sum   %llu\n\n",sum);
//        printf("***a[x]  %llu\n\n",a[x]);
//        printf("***aa[x]   %llu\n\n",aa[x]);
//        printf("***summ  %llu\n\n",summ);
//        printf("***ans  %llu\n\n",ans);
        ull res=summ*a[x];///构成整循环的和
        for(ull i=1; i<=ans; i++)
        {
            if(x==1)
                res+=gm[i].b1;
            if(x==2)
                res+=gm[i].b2;
            if(x==3)
                res+=gm[i].b3;
            if(x==4)
                res+=gm[i].b4;
            if(x==5)
                res+=gm[i].b5;
            if(x==6)
                res+=gm[i].b6;
            if(x==7)
                res+=gm[i].b7;
            if(x==8)
                res+=gm[i].b8;
            if(x==9)
                res+=gm[i].b9;
        }
        printf("%llu\n",res);
    }
    return 0;
}

肯定有简单的实现

AC:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#define Up(i,a,b) for(int i=a;i<=b;i++)///又get到一种简写的方法
typedef long long ll;
using namespace std;
int main()
{
    int q;
    scanf("%d",&q);
    while(q--)
    {
        ll n,m,sum=0;
        scanf("%lld %lld",&n,&m);
        ll num=n/m;///1~n这个区间有多少符合的数
        Up(i,1,9)
        {
            ll d=(m*i)%10;///d表示m可能的个位数
            ll cnt=num/10+(num%10>=i);///cnt表示以d结尾的&&能整除m的数的个数
            sum+=cnt*d;///求和
        }
        printf("%lld\n",sum);
    }
    return 0;
}