zoukankan      html  css  js  c++  java
  • NOIP模拟题——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)) mod (109+7)的值 。
    【样例输入】
    3
    3
    10
    100000
    【样例输出】
    11
    217
    507231491
    【数据规模与约定】
    对于 30%的数据, 1≤N≤10³。
    对于 60%的数据 ,1≤N≤106。
    对于 100%的数据 ,1≤N≤109,1≤T≤2×10³。

    看到题直接懵B。。10的9次方

    然后写了一个暴力程序,直接算出1到1000000的last,发现只能过30%

    部分暴力代码:

     1 last[1]=1,last[2]=3;int q=2;
     2 a[1].left=a[1].right=1;
     3 a[2].left=2;a[2].right=3;
     4 for(int i=3;i<=1400000;i++)
     5 {
     6     last[i]=last[i-1]+q;
     7     a[i].right=last[i];
     8     a[i].left=last[i-1]+1;
     9     if(i>=last[temp])
    10     {
    11         q++;temp++;
    12     }
    13 }

    搞了很久才明白60%是怎么做的:

    首先打表找出last和last(last) (这里只写10组):

    x                1    2    3    4    5     6     7    8      9      10

    a[x]               1    2    2    3    3     4     4    4       5      5 

    last(x)    1    3    5    8    11   15   19  23    28    33

    last(last(x))    1    5    11  23  38   62   90  122  167  217

    撒子也不晓得…………

    outfutr2330讲解过后才发现神奇算法:算last(last(x))-last(last(x-1)):

    last(last(x))-last(last(x-1))      1  4  6  12  15  24  28  32  45  50

    又可以写成:                         1*1   2*2  2*3   3*4   3*5    4*6    4*7    4*8    4*9    5*10

    可以看出,后面的数1~10就等于i,而前面的数刚好就是a[x]

    于是预处理的时候就将各个分块(a[x]相同的为一块)的left和right保存起来,这样依次用等差序列求和公式就能得出ans了

    至于n在中间的情况(如last(last(7)),就用a[4]的right和n(7)做比较,n小则只加上left到n的等差序列,这样就可以过60%的数据

    至于100%的数据,要用到前缀和和二分的方法:前缀和求前面连续分块的和,二分求出离n最近的a[rightn].right的编号rightn,

    再加上后面的等差序列(同上),可以算出大约第130万个分块的长度超过了1e9,所以二分是可行的。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 using namespace std;
     5 const long long maxn=1400000+7;
     6 const long long mod=1e9+7;
     7 int n,t;
     8 long long last[maxn];
     9 long long llst[maxn];
    10 long long k[maxn];
    11 struct node{
    12     long long left,right;
    13 }a[maxn];
    14 long long temp=2;
    15 int main()
    16 {
    17     freopen("nan.in","r",stdin);
    18     freopen("nan.out","w",stdout);
    19     last[1]=1,last[2]=3;int q=2;
    20     a[1].left=a[1].right=1;
    21     a[2].left=2;a[2].right=3;
    22     for(int i=3;i<=1400000;i++)
    23     {
    24         last[i]=last[i-1]+q;
    25         a[i].right=last[i];
    26         a[i].left=last[i-1]+1;
    27         if(i>=last[temp])
    28         {
    29             q++;temp++;
    30         }
    31     }
    32     
    33     for(int i=1;i<=1400000;i++)
    34     {
    35         k[i]=k[i-1]+(a[i].right-a[i].left+1)*i*(a[i].left+a[i].right)/2%mod;
    36         k[i]%=mod;
    37     }
    38     scanf("%d",&t);
    39     long long ans=0;
    40     for(int i=1;i<=t;i++)
    41     {
    42         int n;scanf("%d",&n);
    43         int leftn=1,rightn=1400000;
    44         while(leftn<=rightn)
    45         {
    46             int mid=(leftn+rightn)>>1;
    47             if(a[mid].right<n)leftn=mid+1;
    48             else rightn=mid-1;
    49         }
    50         ans=k[rightn];
    51         ans+=(rightn+1)*(n-a[rightn].right)*(a[rightn+1].left+n)/2%mod;
    52         printf("%I64d
    ",ans%mod);
    53     }
    54     return 0;
    55 }
  • 相关阅读:
    HDU 1501 Zipper(DFS)
    HDU 2181 哈密顿绕行世界问题(DFS)
    HDU 1254 推箱子(BFS)
    HDU 1045 Fire Net (DFS)
    HDU 2212 DFS
    HDU 1241Oil Deposits (DFS)
    HDU 1312 Red and Black (DFS)
    HDU 1010 Tempter of the Bone(DFS+奇偶剪枝)
    HDU 1022 Train Problem I(栈)
    HDU 1008 u Calculate e
  • 原文地址:https://www.cnblogs.com/937337156Zhang/p/6020751.html
Copyright © 2011-2022 走看看