蓝桥杯 历届试题 数字游戏 (已AC)
来源:互联网 发布:51单片机入门书籍 编辑:程序博客网 时间:2024/06/07 11:57
游戏的规则是这样的:栋栋和同学们一共n个人围坐在一圈。栋栋首先说出数字1。接下来,坐在栋栋左手边的同学要说下一个数字2。再下面的一个同学要从上一个同学说的数字往下数两个数说出来,也就是说4。下一个同学要往下数三个数,说7。依次类推。
为了使数字不至于太大,栋栋和同学们约定,当在心中数到 k-1 时,下一个数字从0开始数。例如,当k=13时,栋栋和同学们报出的前几个数依次为:
1, 2, 4, 7, 11, 3, 9, 3, 11, 7。
游戏进行了一会儿,栋栋想知道,到目前为止,他所有说出的数字的总和是多少。
1 < n,k,T < 1,000,000;
这个题看似很简单,从头到尾,挨个算,挨个加就行,一开始我的思路也是这样的,于是就写出了这样一个代码,得了66分,后两个超时。
#include <iostream>using namespace std; int main(){int n,k,t,tmp=1;long long sum=0;cin>>n>>k>>t;for(int i=1;i<=(t-1)*n+1;i++)//从头开始把所有序列都算出来{tmp=(tmp+i-1)%k;if(i%n==1)sum+=tmp; }cout<<sum<<endl;return 0;}
再后来,我找到一个规律(下文中n,k,t与原题中含义相同)
当k为偶数时,同学们数数的序列是以2*k为周期循环的
当k为奇数时,同学们数数的序列是以k为周期循环的
例如当k=13时数数序列为
1 2 4 7 11 3 9 3 11 7 4 11 2 4 7 11 3 9 3 11 7 4 1……
例如当k=12时数数的序列为
1 2 4 7 11 4 10 5 1 10 8 7 7 8 10 1 5 10 4 11 7 4 2 11 2 4 7 11 4 10 5 1 10 8 7 7 8 10 1 5 10 4 11 7 4 2 1…………
于是我我们可以把一个周期的序列制成一个表格,然后每次只读出栋栋数的那个数就可以,将一个周期的序列从0开始编号,存储到一个Num容器里,每次只读栋栋数的数,这样速度大大加快。
提交结果得了83分,原因是栋栋的数的数的编号可能超过了long long范围
#include <iostream>#include <vector>using namespace std;vector<int> Num;int main(){int n,k,t,tn;long long sum=0,No,tmp=1;cin>>n>>k>>t;tn=(k%2==0)?2*k:k; for(int i=0;i<tn;i++)//将数数的序列的一个周期制作成一个表格存储{tmp=(tmp+i)%k;Num.push_back(tmp);}for(int i=0;i<t;i++){No=i*n;//No用来计算栋栋数的数的编号sum+=Num[No%tn]; }cout<<sum<<endl;return 0;}
转念一想既然数数的序列有规律,那么栋栋数的数的编号,是不是也有周期性规律
栋栋数的数的编号是以k为周期循环的
比如当k=13时栋栋数的数在Num中编号的序列是
0 3 6 9 12 2 5 8 11 1 4 7 100 3 6 9 12 2 5 8 11 1 4 7 10……
比如当k=12时栋栋数的数在Num中编号的序列是:
0 2 4 6 8 10 12 14 16 18 20 220 2 4 6 8 10 12 14 16 18 20 22……
这样我们只需要算出栋栋数的数的编号的一个周期的和,看看数了几个周期,最后加上不足一个周期数的数的和即可
AC代码:
#include <iostream>#include <vector>using namespace std;vector<int> Num,No;int main(){int n,k,t,tn,tmp1=1,tmp2=0;long long sum=0,tsum=0;cin>>n>>k>>t;tn=(k%2==0)?2*k:k;No.push_back(0);for(int i=0;i<2*tn;i++){tmp1=(tmp1+i)%k;Num.push_back(tmp1);tmp2=(tmp2+n)%tn;//为了方便,当k为偶数时,栋栋数的数的编号序列我取2*k为一个周期No.push_back(tmp2);}for(int i=0;i<tn;i++)//算出一个数数周期数的数的和tsum+=Num[No[i]];for(int i=0;i<t%tn;i++)//算出不足一个数数周期时数的数的和sum+=Num[No[i]];sum+=(tsum*(t/tn));//看看数了几个周期cout<<sum<<endl;return 0;}
还有一种方法,就是看跳步数,拿上面的例子n=3,k=13,t=3来说
可以设栋栋开始数的数为num=1设初始和sum=1,,跳步为step=(3+1)*3/2=6
下一个num=1+6=7,sum=1+7=8,跳步step=(4+6)*3/2=15
下一个num=1+6+15=22,超过了12,于是22%13=9,sum=1+7+8+9=17,跳步=(7+9)*3/2=24
于是我们发现一个规律,跳步数为初始值为(n*1)*n/2,公差为n*n的等差数列,num每次超过k-1,都要对k取余
这样就简单了,代码如下
已AC
#include <iostream>using namespace std;int main(){long long n,k,t;long long sum=1,num=1,step;//注意step,num,sum都要设为long longcin>>n>>k>>t;step=(n+1)*n/2;//初始stepfor(int i=1;i<t;i++){num+=step; step+=n*n;if(num>=k-1)num%=k;sum+=num;} cout<<sum<<endl;return 0;}
- 蓝桥杯 历届试题 数字游戏 (已AC)
- 蓝桥杯--历届试题 数字游戏
- 蓝桥杯 历届试题 数字游戏
- 蓝桥杯 历届试题 数字游戏
- 蓝桥杯 历届试题 数字游戏
- 蓝桥杯 历届试题 数字游戏
- 历届试题 数字游戏
- 历届试题 数字游戏
- 历届试题 数字游戏
- 历届试题 数字游戏
- 历届试题 数字游戏
- 历届试题 数字游戏
- 蓝桥杯历届试题之数字游戏
- 蓝桥杯 -- 历届试题 数字游戏【数学题,值得一看】
- 蓝桥杯 历届试题之数字游戏
- 蓝桥杯历届试题——数字游戏
- 蓝桥杯 历届试题 数字游戏 部分超时
- 2016蓝桥杯历届试题——数字游戏
- 基础练习 十六进制转八进制 (java)
- GIT 命令集
- 如何为一段buffer带上一个头?
- 函数的四种调用模式
- kafka集群安装与使用
- 蓝桥杯 历届试题 数字游戏 (已AC)
- 超好用的Android日志打印框架--Logger
- Win7 Apache部署Django(二)
- adb androdi debug
- 详解Java中的checked异常和unchecked异常
- 超好用的Android日志打印框架--Logger
- 20170325 mycat 堆溢出
- eclipse使用link方式安装插件
- nginx 运维