数字游戏

问题描述

  栋栋正在和同学们玩一个数字游戏。

  游戏的规则是这样的:栋栋和同学们一共n个人围坐在一圈。栋栋首先说出数字1。接下来,坐在栋栋左手边的同学要说下一个数字2。再下面的一个同学要从上一个同学说的数字往下数两个数说出来,也就是说4。下一个同学要往下数三个数,说7。依次类推。

  为了使数字不至于太大,栋栋和同学们约定,当在心中数到 k-1 时,下一个数字从0开始数。例如,当k=13时,栋栋和同学们报出的前几个数依次为:
  1, 2, 4, 7, 11, 3, 9, 3, 11, 7。

  游戏进行了一会儿,栋栋想知道,到目前为止,他所有说出的数字的总和是多少。
输入格式
  输入的第一行包含三个整数 n,k,T,其中 n 和 k 的意义如上面所述,T 表示到目前为止栋栋一共说出的数字个数。
输出格式
  输出一行,包含一个整数,表示栋栋说出所有数的和。
样例输入
3 13 3
样例输出
17
样例说明
  栋栋说出的数依次为1, 7, 9,和为17。
数据规模和约定
  1 < n,k,T < 1,000,000;

Algorithm

最近感冒,大脑有点不好使,先是斐波那契函数,又来一个简单的数列都不会了。

先写一篇博客安慰一下这几天没有发博客的自己!

这种题型,都司空见惯了,看了下数据,一般模拟都会超时,再有,模拟大家都会,肯定不会让你模拟就过关。

数列,那么就可以有A(n)和S(n)的通项公式,我们可以直接求出我们需要的那一项,唯一需要注意的就是一旦数据过大,就会爆掉,为此我还用了快速乘,发现,没什么用,后来发现是知识不到位......

Mathtype敲公式很烦,博客园又不支持markdown,所以我就手打了。

好,现在我们知道A(1) = 1

- A(0) = 1;
- A(n) = n + A(n-1)
- A(n-1) = n-1 + A(n-2)
- A(n-2) = n-2 + A(n-3)
- ......
- A(2) = 2 + A(1)
- A(1) = 1 + A(0)
- A(0) = 0 + 1

很容易得到A(n) = A(0) + S(n)

其中,S(n)为等差数列n的前n项和。

关键在于,我们求A(2n)时,

不用再次求S(n),而是直接加上 n*n

这相当于之前的每一项都加上 n,这样数据就不会爆掉。

A(2n) = A(n) + s(n) + n*n


AC

 1 /*
 2 - A(0) = 1;
 3 - A(n) = n + A(n-1)
 4 - A(n-1) = n-1 + A(n-2)
 5 - A(n-2) = n-2 + A(n-3)
 6 - ......
 7 - A(2) = 2 + A(1)
 8 - A(1) = 1 + A(0)    
 9 - A(0) = 0 + 1
10 */
11 #include<iostream>
12 #include<cstring>
13 using namespace std;
14 
15 typedef long long ll;
16 
17 // 快乘 
18 ll QMul(ll a, ll b)
19 {
20     if(a < b) {a ^= b;b ^= a;a ^= b;}
21     ll s = 0;
22     while(b)
23     {
24         if(b&1) s += a;
25         a = (a<<1);
26         b >>= 1;
27     }
28     return s;
29 }
30 
31 int main()
32 {
33     ll n, k, T;
34     n = k = T = 0;
35     while(cin>>n>>k>>T)
36     {
37         ll s = 1, an = 1, c = n*(n+1)/2;T--;
38         while(T--)
39         {
40             an = (an + c)%k;
41             s += an;
42             c += QMul(n, n);
43         }
44         cout<<s<<endl;
45     }
46     
47     return 0;
48 }
View Code

2019-01-22

12:16:49

原文地址:https://www.cnblogs.com/mabeyTang/p/10303123.html