NOIP模拟赛 t3 nan
2017-07-07 18:43
351 查看
模拟赛的名字都好迷啊23333
nan
【问题描述】
我们有一个序列,现在他里面有三个数1,2,2 。我们从第三个数开始考虑:
1、第三个数是2,所以我们在序列后面写2个3,变成 1,2,2, 3, 3。
2、第四个数是3,所以我们在序列后面写3个4,变成 1, 2, 2, 3, 3, 4,4,4。
那么你可以看到,这个序列应该是 1,2,2,3,3,4,4,4,5,5,5,6,6,6,6,…。
如果我们设一个数x最后出现的位置为last(x),那么现在我希望知道 last(last(x))等于多少。
【输入格式】
第一行一个整数T,代表数据组数。
接下来T行每行一个整数x 。
【输出格式】
T行,每行一个整数,代表last(last(x))%(10^9+7) 的值。
【样例输入】
3
3
10
100000
【样例输出】
11
217
507231491
【样例解释】
╭︿︿︿╮
{/ o o /}
( (oo) )
︶︶︶
【数据规模与约定】
对于30% 的数据, 1<=x<=10^3。
对于60%的数据, 1<=x<=10^6。
对于100%的数据,1<=x<=10^9,1<=T<=2*10^3 。
考试的时候看到这道题内心窃喜,以为自己打表就可以过60%了。
然后。
数组简直怎么开都开不够啊,too large。最后还是只打了30分的表。
于是想尽了办法优化暴力(…)结果最后打表的程序根本交不上,早知道就把暴力交上去了还有30分。
题目分析:
如果对每个数x,直接存每个数的last,甚至是last(last(x)),无疑都是会爆空间的。考虑分区间来做。
对于原序列:
1,2,2,3,3,4,4,4,5,5,5,6,6,6,6,7,7,7,7,…
last[i]=1+2*2+3*2+…+(i-1)*num[i-1]+num[i];
其中num[i]表示这个数出现的次数
对于每个数字出现的次数再确定一个序列:
1,2,2,3,3,4,4,4,5,…
是不是特别神奇。。。
我们可以把出现次数相同的数划在同一个区间,则原序列可以划分为:
1|2,2,3,3,|4,4,4,5,5,5,|6,6,6,6,7,7,7,7,…
对第i个区间,数字出现的次数为i。
last[last[i]]其实就相当于求第二个序列(划分区间)后的last[i]。
[据大佬说暴力算一下最后跑1e9大概一百四十万个区间就够了,这样数组和时间复杂度都是可以接受的]
怎么求啊?
对于每个区间利用两个数组left,right,分别存储区间最左边的数和最右边的数。不难发现区间i最右边的数就是last[i]。
而last[i]其实可以转化为求和了,而且是等差求和。
我们可以维护一个前缀和表示区间1到区间i的和。但算的是每个区间,要回到原序列就还要再乘个数。
而输入的数n很有可能是在区间中间,而不是卡在区间的两端。
所以我们还要对n所在的区间里的和再处理。先二分找到n所在的区间,然后再利用等差求和处理区间内部。
为什么前缀和sum[i]对应的就是last[last[i]]?
还是看这个序列:
1,2,2,3,3,4,4,4,5,5,5,6,6,6,6,…
还是举栗子吧:last[3]=5,
而在num[i]的序列中:
(last[i]=sum[i])
1,2,2,3,3,4,4,4,5,5,5,6,6,6,6,…
5对应的那个数又是第二次出现的3 (这个是显然的,对任意都成立,根据这个数列的形成方式)
所以last[5]=sum[3];
所以last[last[i]]=sum[i]
具体看代码吧。
nan
【问题描述】
我们有一个序列,现在他里面有三个数1,2,2 。我们从第三个数开始考虑:
1、第三个数是2,所以我们在序列后面写2个3,变成 1,2,2, 3, 3。
2、第四个数是3,所以我们在序列后面写3个4,变成 1, 2, 2, 3, 3, 4,4,4。
那么你可以看到,这个序列应该是 1,2,2,3,3,4,4,4,5,5,5,6,6,6,6,…。
如果我们设一个数x最后出现的位置为last(x),那么现在我希望知道 last(last(x))等于多少。
【输入格式】
第一行一个整数T,代表数据组数。
接下来T行每行一个整数x 。
【输出格式】
T行,每行一个整数,代表last(last(x))%(10^9+7) 的值。
【样例输入】
3
3
10
100000
【样例输出】
11
217
507231491
【样例解释】
╭︿︿︿╮
{/ o o /}
( (oo) )
︶︶︶
【数据规模与约定】
对于30% 的数据, 1<=x<=10^3。
对于60%的数据, 1<=x<=10^6。
对于100%的数据,1<=x<=10^9,1<=T<=2*10^3 。
考试的时候看到这道题内心窃喜,以为自己打表就可以过60%了。
然后。
数组简直怎么开都开不够啊,too large。最后还是只打了30分的表。
于是想尽了办法优化暴力(…)结果最后打表的程序根本交不上,早知道就把暴力交上去了还有30分。
题目分析:
如果对每个数x,直接存每个数的last,甚至是last(last(x)),无疑都是会爆空间的。考虑分区间来做。
对于原序列:
1,2,2,3,3,4,4,4,5,5,5,6,6,6,6,7,7,7,7,…
last[i]=1+2*2+3*2+…+(i-1)*num[i-1]+num[i];
其中num[i]表示这个数出现的次数
对于每个数字出现的次数再确定一个序列:
1,2,2,3,3,4,4,4,5,…
是不是特别神奇。。。
我们可以把出现次数相同的数划在同一个区间,则原序列可以划分为:
1|2,2,3,3,|4,4,4,5,5,5,|6,6,6,6,7,7,7,7,…
对第i个区间,数字出现的次数为i。
last[last[i]]其实就相当于求第二个序列(划分区间)后的last[i]。
[据大佬说暴力算一下最后跑1e9大概一百四十万个区间就够了,这样数组和时间复杂度都是可以接受的]
怎么求啊?
对于每个区间利用两个数组left,right,分别存储区间最左边的数和最右边的数。不难发现区间i最右边的数就是last[i]。
而last[i]其实可以转化为求和了,而且是等差求和。
我们可以维护一个前缀和表示区间1到区间i的和。但算的是每个区间,要回到原序列就还要再乘个数。
而输入的数n很有可能是在区间中间,而不是卡在区间的两端。
所以我们还要对n所在的区间里的和再处理。先二分找到n所在的区间,然后再利用等差求和处理区间内部。
为什么前缀和sum[i]对应的就是last[last[i]]?
还是看这个序列:
1,2,2,3,3,4,4,4,5,5,5,6,6,6,6,…
还是举栗子吧:last[3]=5,
而在num[i]的序列中:
(last[i]=sum[i])
1,2,2,3,3,4,4,4,5,5,5,6,6,6,6,…
5对应的那个数又是第二次出现的3 (这个是显然的,对任意都成立,根据这个数列的形成方式)
所以last[5]=sum[3];
所以last[last[i]]=sum[i]
具体看代码吧。
#include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; const int N = 1400000 + 10; const int mod = 1e9 + 7; int t; ll left ,right ; int temp;//有多少组 ll ans=0; ll sum ;//求前缀和 int main(){ //freopen("nan.in","r",stdin); //freopen("nan.out","w",stdout); left[1]=1,right[1]=1; left[2]=2,right[2]=3; temp=2; for(int i=3;i<=N - 10;i++){ left[i]=right[i-1]+1; right[i]=right[i-1]+temp; if(i>=right[temp]) temp++;//已经到下一组了 } memset(sum,0,sizeof(sum)); for(int i=1;i<=N - 10;i++){ sum[i]=sum[i-1]+i*(right[i]-left[i]+1)*(left[i]+right[i])/2%mod; sum[i]%=mod; } scanf("%d",&t); while(t--){ int n; scanf("%d",&n); int i=lower_bound(left+1,left+N-9,n)-left-1; //二分查找是第几个区块 ans=sum[i-1]; ans+=(i)*(n-right[i-1])*(left[i]+n)/2%mod; printf("%I64d\n",ans%mod); } return 0; }
相关文章推荐
- 2017.03.18【NOIP 普及组】模拟赛C组 T3:单元格
- NOIP 模拟赛 nan (暴力?)
- JZOJ1491.2017.04.02【NOIP 普及组】模拟赛C组 T3打鼹鼠
- nodgd 好路线 noip 2015 模拟赛 T3
- 【NOIP 模拟题】[山东多校联合模拟赛 day1 T3] Formula 1 (BFS+并查集)
- JZOJsenior2434.2017.04.08【NOIP 普及组】模拟赛C组 T3开关灯泡
- NOIP欢乐模拟赛 T3 解题报告
- 洛谷noip 模拟赛 day1 T3
- NOIP模拟赛 T3:与众不同(线段树+滑动窗口)
- 20161005 NOIP 模拟赛 T3 解题报告
- 2014-5-24 NOIP模拟赛
- #bzoj2933#【重庆市NOIP模拟赛】数据(DP线段树优化 or DP堆优化 + 证明)
- 2016.09.10【初中部 NOIP提高组 】模拟赛C题解
- 洛谷noip 模拟赛 day1 T1
- [NOIP2014]飞扬的小鸟 D1 T3 loj2500 洛谷P1941
- 【NOIP模拟赛】小奇挖矿
- noip模拟赛 双城记
- NOI.AC NOIP模拟赛 第六场 游记
- 【NOIP模拟赛】 permutation 数学(打表)
- 【noip模拟赛】密码