Ncs
2016-07-10 16:57
246 查看
题目描述 Problem Description
某巨魔有条长度为 N 的由红色头骨和绿色头骨组成的项链(当然事实上是没有的),这条项链现在已经断开了。 由于这条项链太长了,巨魔想截取其中一段长度非零的项链作为自己的新项链。 这个巨魔很迷信,它认为截取下来的项链段上如果有正好 M 个红色头骨那么这段项链就可以认为是有利于报复社会的。 它想知道有多少种截取方法使得截下来的项链利于报复社会。 两种截取方法被认为不同当且仅当它们至少有一个截取的位置不同。 当然,巨魔也可以保留这条项链,不截取。输入描述 Input Description
第一行一个数字 M 。第二行一个 01 字符串, 0 表示绿色头骨, 1 表示红色头骨。 该字符串的长度为 N 。
输出描述 Output Description
输出一行,即截下来的项链有利于报复社会的截取方案数。输入样例 Sample Input
11010
输出样例 Sample Output
6提示 Hint
截取方案: [1,1],[1,2],[2,3],[2,4],[3,4],[3,3] 。总共 6 种。数据范围 Data Size
10% 的数据: 1≤N≤100。30% 的数据: 1≤N≤1000 。
100% 的数据: 1≤N≤1000000。0≤M≤1000000 。
分析 I Think
考虑前缀和,记 Si 表示第 i 位(含)之前的 1 的个数, Ri 表示 Sk=i 的个数。如果 n=0 ,那么 ans=∑SNi=1Ri∗Ri+M
如果 n≠0 ,那么 ans=∑SNi=1Ri∗(Ri−1)2
代码 Code
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long LL; const int Size = 1000000+47; char str[Size]; int len; int sum[Size]; int a[Size]; int n; int main(){ scanf("%d%s",&n,str+1); len = strlen(str+1); a[0] = 1; for(int i=1;i<=len;++i) ++a[sum[i]=sum[i-1]+str[i]-'0']; LL ans = 0; if(n) for(int i=0;i<=sum[len];++i) ans += a[i]*a[i+n]; else for(int i=0;i<=sum[len];++i) ans += (a[i]*(a[i]-1)>>1); printf("%lld",ans); return 0; }
相关文章推荐
- 排序复杂度分析
- html初学1
- js中的运算符优先级顺序
- MySql-straight_join优化列
- 功率谱密度相关方法MATLAB实现
- Android软键盘弹出时把布局顶上去,控件乱套解决方法
- 随机映射变换
- 双向链表
- 写出servlet重要的对象有哪些?
- urllib2自定义opener详解
- Linux下的ip命令
- POJ1463->树形DP
- 6、视图的操作----第2篇
- 【PHP面向对象(OOP)编程入门教程】8.构造方法__construct()与析构方法__destruct()
- 简述servlet生命周期
- 非阻塞同步算法与CAS(Compare and Swap)无锁算法
- C#一点点积累
- 软实时和硬实时操作系统的区别
- python学习笔记(四)
- 2016.4-2016.7总结