选博士 题解

发布时间 2023-08-30 09:57:00作者: koukilee

FZQOJ
Luogu

前言

​ 节假日在家 闲来无事 ,那就 写一篇题解吧。

题目描述

​ 前面一大堆废话,总结来说就是:

​ 求 l -- R 区间的和

​ 但是每一个数转换为 它本身所有数位的和,重复这个操作, 直到这个数 ⩽ 9

思路

​ 我不知道各位神犇们是怎么做的,所以在此分享一下我的思路


前缀和(70pts)

这道题乍一眼看,不是前缀和吗!那么,可以写个函数:

int change(int x){
	while(x >= 10){
		int sum = 0;
		while(x)
			sum += x % 10, x /= 10;
		x = sum;
	}
	return x;
}

接着用前缀和记录每一个数就可以了,


But, 但是这道题的数据范围:
​ 1 ⩽ l ⩽ r ⩽ 260


数组直接爆炸,光荣RE


找规律(100pts)

从题目给的样例:

​ A9 = 9, A10 = 1, A11 = 2, A12 = 3 ... A18 = 9, A19 = 1...

不难看出:

​ 这不就是小学学的周期问题吗?每十个数为一个周期。

那么我们就不需要将每一个数通过函数算一遍了,只要算出第一个数的函数值,

通过周期一直推到 R 就可以了


But, 但是这道题还是拿不了满分,于是我们可以再优化一下:

将两数之间的数字 9,可以直接求出有几个周期,并计算和

再加上它的余下的数就行。


最后

处理一下题目的一点细节,那么代码如下(不留坑了吧):

请在理解题目思路后,先自行编写

#include<bits/stdc++.h>
using namespace std;

long long a, b, n;
/*不开long long 会爆*/

long long change(long long x){
    /*change函数,用于计算第一位*/
	while(x >= 10){
		long long sum = 0;
		while(x) sum += x % 10, x /= 10;
		x = sum;
	}
	return x;
}

int main(){
	scanf("%lld", &n);
	for(int i = 1; i <= n; i++){
		scanf("%lld %lld", &a, &b);
		long long t = change(a), ans = 0, xn;
		for(int j = t; j <= 9 && a <= b; j++) 
			ans += j, a++;
        /*方便计算周期*/
		xn = b - a;
		if(xn >= 0){
			ans += xn / 9 * 45;
            /*计算周期间的和*/
			for(int j = 1; j <= xn % 9 + 1; j++){
				ans += j;
			}
            /*加上剩下的数*/
		}
		printf("%lld\n", ans);
	}
	return 0;
}

那么,这道题就光荣AC

咳, 点赞,懂?