zoukankan      html  css  js  c++  java
  • Hdu 5459 Jesus Is Here (2015 ACM/ICPC Asia Regional Shenyang Online) 递推

    题目链接:

      Hdu 5459 Jesus Is Here

    题目描述:

      s1 = 'c', s2 = 'ff', s3 = s1 + s2; 问sn里面所有的字符c的距离是多少?

    解题思路:

      直觉告诉我们,sn肯定由sn-1与sn-2推导出来的。然后呢,我们可以看出 n%2==1 的时候 sn-1 与 sn-2 由 ffff 衔接起来的,n%2==0 的时候,sn-1 与 sn-2由 ff 衔接起来的。告诉队友后,队友就把这个当成重要依据推啊,推啊!!到最后感觉丢队友自己看药丸,放弃02回来和队友一起看,发现这样想脑洞太大,完全错误.......真是真是可怜,这个锅我接!!

      我们先设定len[i], num[i], sum[i], ans[i]分别是:si的长度,si中c的数目,si中c的下标和,si中所有字符c的距离。

      则有:

        len[i]   = len[i-1] + len[i-2];

        num[i] = num[i-1] + num[i-2];

        sum[i] = sum[i-1] + sum[i-2] + len[i-2] * num[i-1];

        ans[i]  = ans[i-1] + ans[i-2] + (len[i-2] * num[i-2] - sum[i-2]) * num[i-1] + num[i-2] * sum[i-1];

      对于len,num很容易理解,就是斐波那契数列。

      sum[i] = sum[i-1] + sum[i-2] 很容易理解,由于si-1在si-2后面,所以对于每一个si-1里面的c来说下标都加上了len[i-2], 然后很自然的就加上 len[i-2] * num[i-1];

      对于ans[i]来说,ans[i]  = ans[i-1] + ans[i-2] 很容易理解,然后还有 si-1 与 si-2 里面的c的距离没有加上。我们把 si 看成两部分,以衔接处为分割线,前部分的贡献值为:(len[i-2] * num[i-2] - sum[i-2]) * num[i-1] ,对于后半部分的每个c来说,前半部分的贡献是相同的,都是前半部分中的每个c的坐标到分割线的位置。后半部分的贡献值为 num[i-2] * sum[i-1],正好与前半部分相反;

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 using namespace std;
     6 typedef long long LL;
     7 const LL maxn = 201320;
     8 const LL mod = 530600414;
     9 LL ans[maxn], len[maxn], sum[maxn], num[maxn];
    10 int main ()
    11 {
    12     LL t, n;
    13     scanf ("%lld", &t);
    14     len[1] = sum[1] = num[1] = 1;
    15     len[2] = 2;
    16     sum[2] = num[2] = 0;
    17     for (int i=3; i<maxn; i++)
    18     {
    19         len[i] = (len[i-1] + len[i-2]) % mod;
    20         num[i] = (num[i-1] + num[i-2]) % mod;
    21         sum[i] = ((sum[i-1] + sum[i-2]) % mod + num[i-1] * len[i-2] % mod) % mod;
    22         ans[i] = ((ans[i-1] + ans[i-2]) % mod + (num[i-2]*len[i-2]-sum[i-2]) % mod*num[i-1] % mod + num[i-2] * sum[i-1] % mod) % mod;
    23     }
    24     for (LL i=1; i<=t; i++)
    25     {
    26         scanf ("%lld", &n);
    27         printf ("Case #%lld: %lld
    ", i, ans[n]);
    28     }
    29     return 0;
    30 }

      

    本文为博主原创文章,未经博主允许不得转载。
  • 相关阅读:
    力扣3. 无重复字符的最长子串
    力扣724. 寻找数组的中心索引
    力扣105. 从前序与中序遍历序列构造二叉树
    力扣541. 反转字符串 II
    力扣496. 下一个更大元素 I
    力扣129. 求根到叶子节点数字之和
    力扣628. 三个数的最大乘积
    力扣415. 字符串相加
    力扣409. 最长回文串
    力扣404. 左叶子之和
  • 原文地址:https://www.cnblogs.com/alihenaixiao/p/4829425.html
Copyright © 2011-2022 走看看