hdu 5439 Aggregated Counting(长春网络赛——找规律+二分)

题目链接: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,T2000 , indicating the number of queries to follow. Each of the following T lines contain a positive number n(n109) 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
  
  
3 3 10 100000
 

Sample Output
  
  
11 217 507231491
 

Source
 

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;
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值