TZOJ. dove and Sweet(找规律+递推)
Posted 须藤要
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了TZOJ. dove and Sweet(找规律+递推)相关的知识,希望对你有一定的参考价值。
Dove and Sweet(找规律+递推)
描述
GoodEnough为了鼓励Dove读书,决定给Dove一些读书的奖励。Dove从第一页开始按顺序读书,从第二页开始,如果Dove读完了第 i 页书,那么Dove的老师会给Dove一些糖果,糖果的个数是 i 和 i−1 的数位和的差的绝对值(例如,对于 i=100,Dove会得到|1+0+0−9−9∣=17颗糖)。Dove想知道如果自己读了 n 页书的话,自己能得到多少糖果呢?
输入
一行,一个整数n,含义如题。
对于60%的数据,n≤5∗10^6
对于100%的数据,n≤10^25000000
输出
一个数,表示得到的糖果数对 1914270647取模的结果。
样例一
输入:10
输出:16
提示:|2−1|+|3−2|+|4−3|+|5−4|+|6−5|+|7−6|+|8−7|+|9−8|+|1+0−9|=16
样例二
输入:1906471427
输出:1517377881
题解
- 由输入可看n的大小是非常大的,对于时间和内存都是非常大的,所以按照普通的暴力一定不会过。因此我们要换种思路,读入一定是一位一位的读,并且是边读边计算sum(获得糖果的数量)的值。
- 首先需要寻找规律,寻找规律可以通过暴力小的数字进行观察,而且糖果是从第二页阅读才开始获得,所以我们可以转换成从第一页开始获得糖果,然后对最终的糖果加上mod的数然后减一取模就可以了。下面是暴力寻找的代码。
#include<cstdio>
typedef long long ll;
const int mod=1914270647;
ll pan(ll a, ll b)
{
ll s = 0;
while (a || b)
{
s = s + a % 10 - b % 10;
a /= 10;
b /= 10;
}
return s < 0 ? -s : s;
}
int main(){
ll s=0,n;
while(scanf("%lld",&n)!=EOF){
s=0;
// s=pan(n,n-1);
for(ll i=2;i<=n;i++){
s=(s%mod+pan(i,i-1)%mod)%mod;
}
printf("%lld\\n",s);
}
return 0;
}
- 因为每阅读一页获得糖果的数是 i 与 i - 1 的数位之差的绝对值,可以想到这个值与最后一个非0数(m)的位置有关,如果m为该数的最后一位,获得的糖果为1(|2 - 1|),假如这个数不是最后一位,这个数的大小取决于末尾0的个数(9 *0的个数-1),又因为每次看书都至少获得一个糖果,就可以把所有末尾有0的那个状态减一个糖果,之后末尾无0状态加上末尾有0减糖出来的那个状态合起来获得的糖果就是n。
n | sum(糖果的个数) |
---|---|
A | A = A-0 |
AB | AB+7A = AB+8A - A |
ABC | ABC+79A+7B = ABC +8AB -(A+B) |
ABCD | ABCD+799A+79B+7C = ABCD+8ABC-(A+B+C) |
观察可得减去的那个数可以最后输出的时候减,并对a,b,s,sum初始化为0。
abc
a表示倒数第三个读入的数
b表示倒数二个读入的数
c表示当前读入的数
因此我们可以写出递推公式sum( i )=sum( i - 1 ) * 10 + 8 * b + c
最终的答案就是sum - s -1;
AC代码:
#include<iostream>
using namespace std;
typedef long long ll;
const ll mod=1914270647;
int main(){
char c;
ll a,b,s,sum;//定义长整数型防止越界
a=b=s=sum=0;
while((c=getchar())!='\\n'){
sum=(sum*10+8*b+c-'0')%mod;//求糖果的数量
a=b;b=c-'0';//将a变为下一次输入时倒数第三个数,将b变为倒数第二个数
s=(s+a)%mod;//求要减去的那个数的和
}
printf("%lld",(mod+sum-s-1)%mod);//保证输出为一个正数
return 0;
}
以上是关于TZOJ. dove and Sweet(找规律+递推)的主要内容,如果未能解决你的问题,请参考以下文章
UVA10765Doves and bombs (BCC求割点后联通块数量)