MM的数学作业

问题描述

今天,MM在上数学课,数学课的主题是函数。讲完以后老师留了一个家庭作业,让同学们回家思考。题目如下:

定义一个函数,F(x)表示x转成二进制后,二进制中“1”的个数。比如F(279)=5,因为(279)10=( 100010111)2,其中有5个“1”。

现在有一个序列,已知X0 = 0,Xi=F(Xi-1)*A+B。老师的问题是求这个序列第K个是多少。

输入格式

输入3个整数,A,B,K,定义如上所述。

输出格式

输出只有一行,序列的第K个的值。

样例输入

1

7

2

样例输出

10

数据范围

0≤A,B≤ 1,000,000

30% 数据1≤K≤1,000,000

100% 数据1≤K≤1,000,000,000

题解

打几个表,然后就发现当K足够大的时候答案就形成一条链加一个环,直接模拟的时间就浪费在这个环上。

找出这个环,求出环的大小并记录环的每一个元素,K减去链的长度,对环的大小取模得到的就是答案在环中的位置。

数组范围开多大?

打开电脑上的计算器,使用程序员型,把106转换成二进制,有20位,那么f(x)的值不会超过20,f(x)*A+B的值不超过20*106+106= 21000000

所以数组范围开21000000

 1 #include <cstdio>
 2 int A,B,K,f[21000005],t=1,h,max;  //  f[1]=0
 3 bool vis[21000005]; 
 4 int main()
 5 {
 6     int x=0,i,j,cnt,p;
 7     scanf("%d%d%d",&A,&B,&K);
 8     vis[0]=1;
 9     while (K--)
10     {
11         for (cnt=0;x;x-=(x&(-x))) cnt++;
12         x=cnt*A+B;
13         if (x>max) max=x;
14         if (!vis[x]) vis[x]=1,f[++t]=x;
15         else break;
16     }
17     if (++K)
18     {
19         for (h=1;f[h]!=x;h++);
20         p=K%(t-h+1);
21         if (!p) printf("%d",f[t]);
22         else printf("%d",f[p+h-1]);
23     }
24     else printf("%d",x);
25     return 0;
26 }
原文地址:https://www.cnblogs.com/rabbit1103/p/9881858.html