本文已参与「新人创作礼」活动,一起开启掘金创作之路。
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] 这个区间内,若存在某个数i是m的倍数,则把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;
}