题解 P4942 【小凯的数字】

Snowflake_Pink

2019-02-01 13:27:51

Solution

## [题面](https://www.luogu.org/problemnew/show/P4942) * 这道题我觉得不应该是绿题啊QAQ,最多应该是黄题吧!题解里面都好像用的是$O(1)$的算法,~~~但是为什么跑的比我慢呢QAQ??~~我觉得可能是mod地太多了吧。。。。 * 分析:我因为太菜了,所以不会这种做法,这题要求的是9的余数,所以就要用到一个众所周知的定理:一个数字各个数位之和除以9的余数等于这个数除以9的余数。**所以我们只需要算出这个数各位之和除9的余数就可以了!!** * 接下来我们“化简”一下:这个数的组成方式是$l(l+1)(l+2)...(r-1)$。所以我们只需要`for (i=l;i<=r;i++)`,算出每个$i$的余数(这里也用上面讲的定理)就可以了。 * 但是!!看看那个100%的数据$(0<l,r \leq 10^{12})$,如果$l=1,r=10^{12}$那一定会超时,在想一下!!我们是否需要将每个$i$都算一遍余数呢??当然不用,每9个相邻的自然数的余数之和为36,正好是9的倍数,所以我们只要把头和尾的一些$i$算一遍余数就可以了。 * Code:下面还有一些细节会在Code中讲解 ```cpp #include <iostream> #include <cstdio> using namespace std; int q; long long l,r,ans,x,y;//不开long long见祖宗 int Mod(long long num){ int t=0; while (num){ t+=num%10;//这里不需要每次都mod一遍,因为int不会爆 num/=10; } t=t%9; return t; } int main(){ long long i; scanf("%d",&q); while (q--){ ans=0; scanf("%lld%lld",&l,&r); for (i=l;i<=r;i++){//开头余数处理 int t=Mod(i); if (t==0) break;//遇到循环节就break ans+=t; } if (i>=r){ printf("%lld\n",ans%9);//要做特判!!!不然上面没有遇到循环节时,余数会算两遍 continue; } for (i=r;i>=l;i--){//末尾余数处理 int t=Mod(i); if (t==0) break; ans+=t; } printf("%lld\n",ans%9);//不会溢出所以不需要每次都mod一遍,尽量避免mod运算!! } return 0; } ``` $PS$:题解有问题来私信我哈~~ 最后贴一个[个人Blog](https://www.17shou.vip/),来我Blog玩耍呀!~~(毫无哲学气息)~~