题解 P4942 【小凯的数字】
蒟蒻第一篇题解,为了发题解学了很长时间markdown,希望审核通过啊,当然如果大家看到了并且能够看明白,那么我再高兴不过了。
题目很简单,就是一串数字对9取模。首先我们要明白一个性质:一个数字除以9的余数等于它的各位数字之和除以9的余数(具体证明过程我就不展示了,建议百度一下,还是很好理解的)。
这样一来我们只需要求解每一位数字的和就行了。可以知道根据题目描述我们可以用等差数列的求和公式来求得各位数字之和。
那么又出现问题了,直接求和是很容易爆掉long long的,那么我们要考虑对它中途进行取模。
取模过程中又会出现一个问题:我们知道a# 乘b%c=(a%c乘b%c)%c,可是在求和公式中,出现了除法,出现了除法又应该怎么办呢?
很容易的看到,我们可以将求和公式拆成两个式子相乘的形式,
比如原式为
(l+r)*(r-l+1)/2//等差数列求和公式,l+r为首项加尾项,r-l+1为项数
我们可以拆分成两个式子:
(l+r)与(r-l+1)/2
或者
(l+r)/2与(r-l+1)
这样分别对它们进行取模操作之后再次进行相乘取模。
接下来我们再来面对下一个问题:这样会出现小数。
由于我们无法知道这两个拆分的式子哪一个是偶数,因此这样一来由于long long是整型,计算过程中我们要除以二,如果是除以二的那个式子的分子是奇数,那么就容易出问题。因此我们要判断哪一个是偶数。 我们可以先判断(l+r)与(r-l+1)哪个是偶数,然后让偶数的那一个除以二,接下来再进行取模相乘再取模,这样就大功告成了!
接下来是我的代码(注意我的n和m分别代表的是题目中的l与r)
#include <iostream>
using namespace std;
long long n,m,k;
int main()
{
cin>>k;
long long x,y;
while(k--)
{
cin>>n>>m;//n与m分别代表题目里的l与r,
if((m+n)%2==0)//拆分等差数列求和公式的关键
{
x=(m+n)/2;//当m+n为偶数时,让它除以二作为其中一个因式
y=m-n+1;//m-n+1必然为奇数,
}
else {
x=(m-n+1)/2;//m-n+1为偶数
y=m+n;
}
cout<<(x%9*y%9)%9<<endl;//用拆分后的两个式子作为等差数列求和公式
}
return 0;
}