HDU - 5439--Aggregated Counting (强大的思维)

题目链接:https://vjudge.net/problem/HDU-5439

                                             Aggregated Counting

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 nn, First of all, find out the position of the last nn 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

3
3
10
100000

Sample Output

11
217
507231491

题目大意:题意很简单,让你求 给定一个n,找到n出现的最后位置p,再找p出现的最后位置。

题目思路:

先定义两个数组 g[]和f[]。

g[i]表示i连续出现了几次,即i位置上放的数。

f[i]表示数字i最后出现的位置。

后面去计算g[i]的时候就可以考虑的是找到第 i 个位置在那个f[]的区间内  , 如果f[k-1]< i <= f[k]

那么说明此时 g[i] = k

那么就可以logn的复杂度计算g[n]了

 

要计算最后的答案,要考虑的是,给定的n,找到最后出现的p,中间长度 p = f[p] = g[1]+g[2]....+g[p]

然后再找对应的ans ,那么每次增加的g[i],就会让整个序列 的长度增加 i*g[i]

i*g[i] 可以理解为的是,长度为i的数量有g[i]个, 所以总长度是i*g[i]

所以ans = sigma(i*g[i]) i<=n

那么对于n <= 1e9

那么大致计算一下会发现f[500000]>1e9

所以g[n]<500000只要暴力求出前500000的g[] , f[]

那么答案计算前,先找到g[n]是多少

g[n]= lower_bound(f+1 , f+N+1 , n)-f

然后说明[1 , g[n]-1]这一段区间内的所有长度都被用到了

所以之前预处理这个长度的前缀和 sum[]

对于每一个长度 i ,他出现的次数都是 f[i]-f[i-1]

sigma(n*g[n]) f[i-1]<n<=f[i]  -> g[n] = i

那么答案就是 i*等差数列了,记得取模(⊙o⊙)哦

然后(g[n]-1 , g[n]]这一段只要枚举 (g[n]-1 , n] 就可以了

思路来自:https://www.cnblogs.com/CSU3901130321/p/4805973.html

标注一下sum[]数组的含义:

sum[i]表示出现次数为i的数的最后位置的最后位置。例如sum[2]=11(数字2和数字3的出现次数为2,3的最后位置是5,5的最后出现位置是11)

AC代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <vector>
#include <string>
#define cla(a, sum) memset(a, sum, sizeof(a))
#define rap(i, m, n) for(i=m; i<=n; i++)
#define rep(i, m, n) for(i=m; i>=n; i--)
using namespace std;
typedef long long ll;
typedef pair<ll, ll> P;
const int Inf = 0x3f3f3f3f;
const double eps = 1e-8;
const int maxn = 5e5+5;
const int MOD = 1000000007;

ll T,n;
ll f[maxn],g[maxn];
ll sum[maxn];

void init()
{
	f[1]=1;f[2]=3;
	g[1]=1;g[2]=2;
	ll i,j,k;
	for(i=3;i<=5e5;i++){
		j=lower_bound(f+1,f+i,i)-f;	
        g[i]=j;
        f[i]=f[i-1]+g[i];
	}
	sum[1]=1;
	for(i=2;i<=5e5;i++){
		sum[i]=sum[i-1]+(f[i]+f[i-1]+1)*g[i]/2%MOD*i%MOD;
		sum[i]=sum[i]%MOD;
	}
}

int main()
{
    init();
    cin>>T;
    while(T--){
    	cin>>n;
    	ll pos=lower_bound(f+1,f+maxn-1,n)-f;
    	ll ans=sum[pos-1];
    	ll i,j;
    	for(i=f[pos-1]+1;i<=n;i++){
    		ans=(ans+pos*i%MOD)%MOD;
		} 
		cout<<ans<<endl;
	}
	return 0;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值