• Hdu 5439 Aggregated Counting (2015长春网络赛 ACM/ICPC Asia Regional Changchun Online 找规律)


    题目链接:

      Hdu 5439 Aggregated Counting

    题目描述:

      刚开始给一个1,序列a是由a[i]个i组成,最后1就变成了1,2,2,3,3,4,4,4,5,5,5.......,最后问a[i]出现n次(i最大)时候,i最后一次出现的下标是多少?

    解题思路:

      问题可以转化为求a[i] == n (i最大),数列前i项的和为多少。

      index:  1  2  3  4  5  6  7  8  9  10

      a:          1  2  2  3  3  4  4  4  5  5

      可以观察出:ans[1] = 1,  ans[i] = ans[i-1] + a[i]*i;

      但是n<=1e9,打不了这个庞大的表。进一步观察,可以发现a数组里面有很多的重复元素,辣么就可以对a数组里面的元素进行压缩存进b数组里面(出现次数为i的最后一个元素为b[i]):

      index:  1  2  3  4  5   6  7  8  9  10

      a:          1  2  2  3  3   4  4  4  5  5

      b:          1  3  5  8  11  15  19  23   28  33

      ans:       1  11  38    122  272  596  1086  

      1到出现次数为i的最后一个元素的区间和为ans[i],由a[]可以看出ans[i] = ans[i-1] + (b[i] + b[i-1] + 1) * (b[i] - b[i-1]) / 2 * i;

      每次查询的时候如果n不在b[i]里面,可以找到一个最接近n并且小于n的b[i],然后再套用一次等差数列求和即可。

      还有就是等差数列求和的时候,除以2要用到逆元处理一下。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 using namespace std;
     6 
     7 typedef __int64 LL;
     8 const int INF = 0x3f3f3f3f;
     9 const int maxn = 450000;
    10 const int mod = 1000000007;
    11 LL a[maxn], b[maxn], ans[maxn], num;
    12 
    13 LL quick_mod(LL x, LL n)
    14 {
    15     LL res = 1;
    16 
    17     while (n)
    18     {
    19         if (n % 2)
    20             res = (res * x) % mod;
    21 
    22         x = (x * x) % mod;
    23         n /= 2;
    24     }
    25     return res % mod;
    26 }
    27 void init ()
    28 {
    29     LL res = 1, j = 1, nu;
    30 
    31     a[0] = b[0] = 0;
    32     a[1] = b[1] = 1;
    33     a[2] = num = 2;
    34     b[2] = 3;
    35 
    36     while (b[num] <= 1e9)
    37     {
    38         if (res <= num)
    39         {
    40             j ++;
    41             res += a[j];
    42         }
    43 
    44         while (res > num)
    45         {
    46             num ++;
    47             a[num] = j;
    48             b[num] = b[num-1] + a[num];
    49         }
    50 
    51     }
    52 
    53     //printf ("%I64d %I64d
    ", num, b[num]);
    54 
    55     ans[0] = 0;
    56     ans[1] = 1;
    57 
    58     for (int i=2; i<=num; i++)
    59          ans [i] = (ans[i-1] + (b[i] + b[i-1] + 1) % mod * a[i] % mod * i % mod * quick_mod(2, mod-2) % mod) % mod;
    60 
    61 }
    62 
    63 int main ()
    64 {
    65     LL t, n;
    66     init ();
    67     scanf ("%I64d", &t);
    68 
    69     while (t --)
    70     {
    71         scanf ("%I64d", &n);
    72         LL pos = lower_bound (b, b+num, n) - b;
    73 
    74         if (b[pos] == n)
    75         {
    76             printf ("%I64d
    ", ans[pos]);
    77             continue;
    78         }
    79 
    80         LL res = (ans[pos-1] + (b[pos-1] + n + 1) % mod * (n - b[pos-1]) % mod * pos % mod * quick_mod(2, mod-2) % mod) % mod;
    81 
    82         printf ("%I64d
    ", res);
    83     }
    84     return 0;
    85 }
    本文为博主原创文章,未经博主允许不得转载。
  • 相关阅读:
    02梦断代码阅读笔记之二
    每日日报
    每日日报
    每日日报
    每日日报
    02梦断代码阅读笔记之一
    每日日报
    SQL语句分为哪几种?
    数据库三范式是什么?
    什么是数据库事务?
  • 原文地址:https://www.cnblogs.com/alihenaixiao/p/4815290.html
Copyright © 2020-2023  润新知