题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5439
Aggregated Counting
Time Limit: 1500/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 665 Accepted Submission(s): 302
Problem Description
Aggregated Counting Meetup (ACM) is a regular event hosted by Intercontinental Crazily Passionate Counters (ICPC). The ICPC people recently proposed an interesting sequence at ACM2016 and encountered a problem needed to be solved.
The sequence is generated by the following scheme.
1. First, write down 1, 2 on a paper.
2. The 2nd number is 2, write down 2 2’s (including the one originally on the paper). The paper thus has 1, 2, 2 written on it.
3. The 3rd number is 2, write down 2 3’s. 1, 2, 2, 3, 3 is now shown on the paper.
4. The 4th number is 3, write down 3 4’s. 1, 2, 2, 3, 3, 4, 4, 4 is now shown on the paper.
5. The procedure continues indefinitely as you can imagine. 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 6, . . . .
The ICPC is widely renowned for its counting ability. At ACM2016, they came up with all sorts of intriguing problems in regard to this sequence, and here is one: Given a positive number
n , First of all, find out the position of the last
n that appeared in the sequence. For instance, the position of the last 3 is 5, the position of the last 4 is 8. After obtaining the position, do the same again: Find out the position of the last (position number). For instance, the position of the last 3 is 5, and the position of the last 5 is 11. ICPC would like you to help them tackle such problems efficiently.
Input
The first line contains a positive integer
T,T≤2000 , indicating the number of queries to follow. Each of the following
T lines contain a positive number
n(n≤109) representing a query.
Output
Output the last position of the last position of each query
n . In case the answer is greater than
1000000006 , please modulo the answer with
1000000007 .
Sample Input
Sample Output
Source
2015 ACM/ICPC Asia Regional Changchun Online
Recommend
hujie | We have carefully selected several similar problems for you: 5664 5663 5662 5661 5660
题目大意::按下列规则生成一组序列,令f(n)为n这个数在序列中出现的最后一个位置,求f(f(n))的值。
解题思路:
令原序列为a,根据定义和序列的生成规则可以推出:
- f(n)等于a的前n项和
- f(n)是n这个数在a中出现的最后一个位置
f(f(n))的含义为:a的前m项和,m为n在a中最后出现的位置。所以f(f(n))的计算式可以写成:
f(f(n))=1 + (2+3)*2 + (4+5)*3 + (6+7+8)*4 + ... + (...+n)*t
大概就是上述的内容,我这里采用了几个数组来存取上述的过程,把公式整理出来。
详见代码。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 450010
const int Mod=(1e9+7);
long long a[N];//表示第i个的结尾数字
int b[N];//表示i出现了几次
long long s[N];//表示前i个和
int main()
{
a[1]=1;
a[2]=3;
a[3]=5;
b[1]=1;
b[2]=2;
b[3]=2;
s[1]=1;
s[2]=11;
s[3]=38;
int k=4,pre=4,kk=3;//k用来循环,pre表示的当前这一列数的下标,kk表示下标对应的数字是多少
while (a[k-1]<=1e9)
{
for (k=pre;k<pre+b[kk];k++)
{
b[k]=kk;
a[k]=a[k-1]+b[k];
s[k]=(s[k-1]+k*((a[k-1]+1+a[k])*(a[k]-a[k-1])/2))%Mod;
}
kk++;
pre=k;
}
int t;
scanf ("%d",&t);
while (t--)
{
int n;
scanf("%d",&n);
int l=1,r=k,mid;
while (l<=r)
{
mid=(r+l)/2;
if (n<=a[mid]&&n>a[mid-1])
{
break;
}
else
{
if (n>a[mid])
{
l=mid+1;
}
else
r=mid;
}
}
printf ("%lld\n",(s[mid-1]+mid*((a[mid-1]+1+n)*(n-a[mid-1])/2))%Mod);
}
return 0;
}