题目链接:点击查看

题目大意:给出一个长度为 n 的数列,现在要求出满足条件的 ( i , j ) 的匹配数量,满足:

题目分析:训练时推的公式,简单说一下吧,维护前缀和 sum,则确定两个断点 ( i , j ) 后可以确定下来三个区间:

  1. sum[ i - 1 ]
  2. sum[ j ] - sum[ i - 1 ]
  3. sum[ n ] - sum[ j ]

因为需要三段区间的权值和连等,根据等式的传递性,我们可以让前两项相等,再让后两项相等,最后不难推出三项连等,建立等式:

  1. 前两项相等:sum[ i - 1 ] = sum[ j ] - sum[ i - 1 ],推得 2 * sum[ j ] = sum[ i - 1 ] * 4(两侧同时乘以 2,下面要用)
  2. 后两项相等:sum[ j ] - sum[ i - 1 ] = sum[ n ] - sum[ j ],推得 2 * sum[ j ] = sum[ n ] + sum[ i - 1 ]

利用 2 * sum[ j ] 当做中间量,不难看出当确定下来 i 后,只有满足 sum[ n ] + sum[ i - 1 ] = sum[ i - 1 ] * 4 时才存在 j 与其匹配,此时只需要查找一下区间 [ i , n ] 中有多少个 j 与其匹配即可


另一种方法,是将其转换成一个很经典的 dp 模型,这里拿一下 PTA 乙级题目的题面:

字符串 APPAPT 中包含了两个单词 PAT,其中第一个 PAT 是第 2 位(P),第 4 位(A),第 6 位(T);第二个 PAT 是第 3 位(P),第 4 位(A),第 6 位(T)。

现给定字符串,问一共可以形成多少个 PAT

比较显然的是,假设 sum 为 n 个数之和,( i , j ) 将整个序列分成的三段大小分别都是 sum / 3(设 sum % 3 == 0),所以第一个断点的位置也就是前缀和等于 sum / 3 的位置,同理第二个断点的位置也就是前缀和等于 sum / 3 * 2 的位置,如此一来就转换成了上面那个非常经典的动态规划模型:

给定 n 个位置,问一共可以形成多少个 ( sum/3 的位置,sum/3*2 的位置)

如此一来这个题目就可以继续扩展了,诸如匹配 ( i , j , k ) 三元对的断点将数列四等分划分这样的

妙啊

代码:
推公式

//#pragma GCC optimize(2)
//#pragma GCC optimize("Ofast","inline","-ffast-math")
//#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=1e6+100;LL sum[N];map<LL,int>mp;int main()
{
#ifndef ONLINE_JUDGE
//  freopen("data.ans.txt","r",stdin);
//  freopen("data.out.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);int n;scanf("%d",&n);for(int i=1;i<=n;i++){LL num;scanf("%lld",&num);sum[i]=sum[i-1]+num;}LL ans=0;for(int i=n-1;i>1;i--)//枚举i  {mp[sum[i]*2]++;if(4*sum[i-1]==sum[n]+sum[i-1]) ans+=mp[sum[n]+sum[i-1]];}printf("%lld\n",ans);return 0;
}

dp

//#pragma GCC optimize(2)
//#pragma GCC optimize("Ofast","inline","-ffast-math")
//#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=1e6+100;LL sum[N],dp[N][2];int main()
{
#ifndef ONLINE_JUDGE
//  freopen("data.ans.txt","r",stdin);
//  freopen("data.out.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);int n;scanf("%d",&n);for(int i=1;i<=n;i++){LL num;scanf("%lld",&num);sum[i]=sum[i-1]+num;}if(sum[n]%3!=0)return 0*puts("0");LL mark=sum[n]/3;for(int i=1;i<=n;i++){for(int j=0;j<2;j++)dp[i][j]=dp[i-1][j];if(i!=n){if(sum[i]==mark)dp[i][0]++;if(sum[i]==mark*2)dp[i][1]+=dp[i-1][0];}}printf("%lld\n",dp[n][1]);return 0;
}

CodeForces - 466C Number of Ways(推公式/dp)相关推荐

  1. Codeforces - 466C - Number of Ways - 组合数学

    https://codeforces.com/problemset/problem/466/C 要把数据分为均等的非空的三组,那么每次确定第二个分割点的时候把(除此之外的)第一个分割点的数目加上就可以 ...

  2. CodeForces - 1459C Row GCD(数论+推公式)

    题目链接:点击查看 题目大意:给出一个长度为 nnn 的数组 aaa,再给出一个长度为 mmm 的数组 bbb,现在要求输出,当 j=1,2,...,mj = 1,2,...,mj=1,2,...,m ...

  3. CodeForces - 1523E Crypto Lights(组合数学+推公式)

    题目链接:点击查看 题目大意:给出 nnn 个初始时熄灭的灯泡,每次操作会等概率打开一个灯泡,当每 kkk 个连续的灯泡中出现了大于一个亮着的灯泡时停止操作,问期望操作次数是多少 题目分析:组合数学题 ...

  4. CodeForces - 830C Bamboo Partition(数学+推公式)

    题目链接:点击查看 题目大意:给出 nnn 个位置可以种竹子,每个位置的竹子的高度需要到达 aia_iai​,所有竹子每天都会长高一个单位高度,同样每个竹子可以在任意位置砍一次,砍过之后竹子将不再长高 ...

  5. ACM - 贪心 - 基础(区间问题 + Huffman树 + 排序不等式 + 绝对值不等式 + 推公式)

    贪心 经典母题 1.区间问题 AcWing 905. 区间选点 AcWing 908. 最大不相交区间数量 AcWing 906. 区间分组 AcWing 907. 区间覆盖 2.Huffman树 A ...

  6. codeforces #274 C. Riding in a Lift dp+前缀和优化

    codeforces #274  C. Riding in a Lift   dp+前缀和优化 Imagine that you are in a building that has exactly  ...

  7. *【CodeForces - 859C 】Pie Rules (博弈dp,时光倒流)

    题干: You may have heard of the pie rule before. It states that if two people wish to fairly share a s ...

  8. Turing Tape (推公式 模拟)

    Turing Tape - CodeForces 132A - Virtual Judge (csgrandeur.cn) 题意: 记录一个数字的前n个二进制数表示的十进制数 int t=s[i];L ...

  9. 2017 icpc 西安赛区 B.Coin(推公式+二项式定理)

    Bob has a not even coin, every time he tosses the coin, the probability that the coin's front face u ...

最新文章

  1. 无边框窗体和用户控件以及权限
  2. java删除有序数组中的重复元素_java去除已排序数组中的重复元素
  3. 异步复位和同步释放电路的详细解释
  4. 体绘制(Volume Rendering)概述之4:光线投射算法(Ray Casting)实现流程和代码(基于CPU的实现)...
  5. [operator]ubuntu + git
  6. cannot be found on object of type xx.CacheExpressionRootObject
  7. 前端学习(1648):前端系列实战课程之任务功能清单思路
  8. java 中创建数据端口_java 如何在服务器端用socket创建一个监听端口,并对接受的数据进行处理,端口号为3333,请高手指点一下...
  9. linux下多线程的创建与等待详解 【转载】
  10. EasyRecovery数据恢复(U盘)
  11. python里countsget_Python Pandas Series.get_dtype_counts()用法及代码示例
  12. 数学建模中的传染病模型及其编程求解
  13. blender做MMD心得(一)
  14. 如何快速翻译医学类英文专业文献?
  15. 基因表达数据处理-Ensembl ID转化为Gene symbol
  16. 一键QQ聊天与一键加群QQ功能
  17. gitpc段提交失败schannel: next InitializeSecurityContext failed: Unknown error (0x80092013
  18. java摇号_java语言实现一个摇号系统,但是可以内部设定中奖名单这个怎么实现?...
  19. 写给大家看的机器学习书【Part3】直观易懂的感知机学习算法PLA
  20. 163相册批量下载程序

热门文章

  1. php warning: file_get_contents,Ecshop报警告:Warning: file_get_contents
  2. 什么是protobuf
  3. 什么是泛型、为什么要使用以及泛型擦除
  4. 为什么任何对象都可以实现锁
  5. ActiveMQ入门-发送消息机制的介绍
  6. 数据源(连接池)的作用
  7. 数据库-第三范式及BCN
  8. 对称加密算法 - Java加密与安全
  9. 顺序表查找+折半查找(二级)
  10. AbstractQueuedSynchronizer源码解析