【8.19校内测试】【背包】【卡特兰数】【数位dp】
早上随便搞搞t1t3就开始划水了,t2一看就是组合数学看着肚子疼...结果t1t3都a了??感天动地。
从小到大排序,从前到后枚举i,表示i是整个背包中不选的物品中代价最小的那个,即i不选,1到i-1全部都要选,i+1到n做背包(此时容量为m-pre),极限复杂度$O(n^3)$,可是我们在中间判断一下,当剩余容量比当前i代价小,break。可以减掉很大的复杂度!(cena评测最慢0.04s~
或者可以在枚举i时倒着枚举,每次背包就可以$O(n)$解决了。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
#define RG register using namespace std; const int mod = ; int n, m, a[];
int f[]; int main ( ) {
freopen ( "gift.in", "r", stdin );
freopen ( "gift.out", "w", stdout );
scanf ( "%d%d", &n, &m );
for ( int i = ; i <= n; i ++ ) {
scanf ( "%d", &a[i] );
}
sort ( a + , a + + n );
ll ans = ; int sum = ;
for ( RG int i = ; i <= n; i ++ ) {
memset ( f, , sizeof ( f ) );
f[] = ;
for ( RG int k = i + ; k <= n; k ++ ) {
if ( m - sum < a[k] ) break;
for ( RG int j = m - sum; j >= a[k]; j -- ) {
f[j] = ( f[j] + f[j-a[k]] ) % mod;
}
}
for ( RG int j = max ( m - sum - a[i] + , ); j <= m - sum; j ++ )
ans = ( ans + f[j] ) % mod;
sum += a[i];
}
printf ( "%d", ans );
return ;
}
题意是要求该序列-1的累加和永远小于等于1的累加和的概率。经典的卡特兰数问题,在坐标系中,可以把-1看成向上走,把1看成向右走,最终目标是计算从原点走到$(n,m)$并且过程中不能超出到$y=x$这条直线的方案数。方案数为$C_{m+n}^m-C_{m+n}^{m-1}$,即$\frac{n-m+1}{n+1}$
#include<iostream>
#include<cstdio>
using namespace std; int main ( ) {
freopen ( "fseq.in", "r", stdin );
freopen ( "fseq.out", "w", stdout );
int T;
scanf ( "%d", &T );
while ( T -- ) {
int n, m;
scanf ( "%d%d", &n, &m );
if ( n < m ) printf ( "0.000000\n" );
else printf ( "%.6lf", ( double ) ( n - m + ) / ( double ) ( n + ) );
}
return ;
}
感觉我的方法是碰巧遇到可以过的类型了...如果题目不合法的对应关系改一下马上就会挂。
但是题目给的是对应不能相同嘛~我定义的$dp[dep][up][tot]$分别表示当前数的位置,是否顶上界,已经填了多少个数(抛开前导零,记忆化的时候会发现,除了顶上界的情况只会计算一次并且不会第二次返回,不顶上界的情况计算一次后每次都直接返回了,不管前面填的什么数和后面将填什么数...
可是对于这道题它恰好就是对的!在不顶上界的情况,所有数字都可以填,并且所有数字都有相同的不合法情况个数!所以直接记忆化就没有问题...
可是$yuli$dalao(%%%指出,只要把题稍微改一改,比如对应位置不能同时为质数之类的...每个数的方案数就不一样了!
所以正解是枚举数的长度,从前后同时填数即可。
#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std; ll dp[][][];
int num[], fi[]; ll dfs ( int dep, int up, int tot ) {
if ( dp[dep][up][tot] ) return dp[dep][up][tot];
if ( !dep && tot ) return ;
if ( !dep ) return ;
int MA = up ? num[dep] : ;
ll res = ;
for ( int i = ; i <= MA; i ++ ) {
if ( i == && !tot ) res += dfs ( dep - , up && i == MA,tot );
else if ( fi[tot + ] != i ) {
fi[dep] = i;
res += dfs ( dep - , up && i == MA, tot + );
fi[dep] = -;
}
}
dp[dep][up][tot] = res;
return res;
} ll work ( ll x ) {
int cnt = ;
memset ( fi, -, sizeof ( fi ) );
memset ( dp, , sizeof ( dp ) );
while ( x ) {
num[++cnt] = x % ;
x /= ;
}
return dfs ( cnt, , );
} int main ( ) {
freopen ( "lucky.in", "r", stdin );
freopen ( "lucky.out", "w", stdout );
ll x, y;
scanf ( "%I64d%I64d", &x, &y );
ll xx = work ( x - ), yy = work ( y );
printf ( "%I64d", yy - xx );
}
// wans
#include <bits/stdc++.h>
using namespace std; typedef long long ll;
ll l,r,dp[][][];
int tot,dig[];
bool vis[][][]; ll dfs(int dep,bool lf_up,bool rg_up) { if(vis[dep][lf_up][rg_up]) return dp[dep][lf_up][rg_up];
if(dep == tot - dep + ) {
if(lf_up && rg_up) return dig[dep];
else if(! lf_up) return ;
else if(lf_up) return dig[dep] + ;
}
if(dep > tot - dep + ) {
if(lf_up && rg_up) return ;
return ;
}
vis[dep][lf_up][rg_up] = true;
int up = lf_up ? dig[tot - dep + ] : ;
ll res = ;
for(int i = ;i <= up;i ++)
for(int j = ;j <= ;j ++) {
if(i == j) continue;
if(dep == && i == ) continue;
bool upup;
if(j > dig[dep]) upup = true;
else if(j < dig[dep]) upup = false;
else upup = rg_up;
res += dfs(dep + ,lf_up && (i == dig[tot - dep + ]),upup);
}
return dp[dep][lf_up][rg_up] = res;
} ll solve(ll s) { memset(vis,,sizeof(vis));
ll ss = s,ans = ;
tot = ;
while(s) {
dig[++ tot] = s % ;
s /= ;
}
ans += dfs(,,);
for(int i = ;i <= tot;i ++) dig[i] = ;
for(tot = tot - ;tot >= ;tot --) {
memset(vis,,sizeof(vis));
ans += dfs(,,);
}
return ans;
} int main( ) { freopen("lucky.in","r",stdin);
freopen("lucky.out","w",stdout);
scanf("%I64d%I64d",& l,& r);
ll ans1 = solve(l - );
ll ans2 = solve(r);
printf("%I64d",ans2 - ans1);
}
//yuli
【8.19校内测试】【背包】【卡特兰数】【数位dp】的更多相关文章
- 【10.17校内测试】【二进制数位DP】【博弈论/预处理】【玄学(?)DP】
Solution 几乎是秒想到的水题叻! 异或很容易想到每一位单独做贡献,所以我们需要统计的是区间内每一位上做的贡献,就是统计区间内每一位是1的数的数量. 所以就写数位dp辣!(昨天才做了数字统计不要 ...
- FZU 1064 教授的测试(卡特兰数,递归)
Problem 1064 教授的测试 Accept: 149 Submit: 364 Time Limit: 1000 mSec Memory Limit : 32768 KB Problem Des ...
- 2018.08.19 NOIP模拟 number(类数位dp)
Number 题目背景 SOURCE:NOIP2015-SHY-10 题目描述 如果一个数能够表示成两两不同的 3 的幂次的和,就说这个数是好的. 比如 13 是好的,因为 13 = 9 + 3 + ...
- 【BZOJ1662】[Usaco2006 Nov]Round Numbers 圆环数 数位DP
[BZOJ1662][Usaco2006 Nov]Round Numbers 圆环数 Description 正如你所知,奶牛们没有手指以至于不能玩"石头剪刀布"来任意地决定例如谁 ...
- 【BZOJ-1026】windy数 数位DP
1026: [SCOI2009]windy数 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 5230 Solved: 2353[Submit][Sta ...
- CCF 201312-4 有趣的数 (数位DP, 状压DP, 组合数学+暴力枚举, 推公式, 矩阵快速幂)
问题描述 我们把一个数称为有趣的,当且仅当: 1. 它的数字只包含0, 1, 2, 3,且这四个数字都出现过至少一次. 2. 所有的0都出现在所有的1之前,而所有的2都出现在所有的3之前. 3. 最高 ...
- bzoj 1026 [SCOI2009]windy数 数位dp
1026: [SCOI2009]windy数 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline ...
- luogu P2657 [SCOI2009]windy数 数位dp 记忆化搜索
题目链接 luogu P2657 [SCOI2009]windy数 题解 我有了一种所有数位dp都能用记忆话搜索水的错觉 代码 #include<cstdio> #include<a ...
- 【BZOJ 3326】[Scoi2013]数数 数位dp+矩阵乘法优化
挺好的数位dp……先说一下我个人的做法:经过观察,发现这题按照以往的思路从后往前递增,不怎么好推,然后我就大胆猜想,从前往后推,发现很好推啊,维护四个变量,从开始位置到现在有了i个数 f[i]:所有数 ...
随机推荐
- CentOS7最小化安装连接到网络的解决方案
周末在家想装个虚拟机学一下Hadoop啥的,因为网速小水管比较慢所以下载的是CentOS的minimal版本的: 这个版本安装完之后默认是没有安装net-tools的,也就是说ifconfig不能用: ...
- 【转载】在GitHub上管理项目
在GitHub上管理项目 新建repository 本地目录下,在命令行里新建一个代码仓库(repository) 里面只有一个README.md 命令如下: touch README.md git ...
- UBuntu14.04 --vim安装YouCompleteMe插件
说明 我电脑的系统参数(用 uname -a命令查看)如下: Linux avyn-Lenovo --generic #-Ubuntu SMP Tue Mar :: UTC i686 i686 i68 ...
- 用于启动 Windows Phone 8 内置应用的 URI 方案
本主题列出了可用于启动内置应用的 URI 方案.许多内置于 Windows Phone 的应用,都可以通过调用 LaunchUriAsync(Uri) 和传入一个使用与要启动应用相关的方案的 URI, ...
- python-unittest学习2--生成报告
上个是小练习 ,这次将unittest模块化一下,也就是吧用例放在case目录下,start放在bin目录下面 -------------------start------------------- ...
- tomcat打开gzip、配置utf-8
在部署描述文件中配置如下内容:(web.xml) 打开gzip compression="on"配置utf-8 URIEncoding="UTF-8" < ...
- HDU 3746 Cyclic Nacklace(KMP找循环节)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2087 题目大意:给你一个字符串,求出将字符串的最少出现两次循环节需要添加的字符数. 解题思路: 这题需 ...
- LeetCode818. Race Car
https://leetcode.com/problems/race-car/description/ Your car starts at position 0 and speed +1 on an ...
- 简单优化:Zipalign
Android SDK中包含一个“zipalign”的工具,它能够对打包的应用程序进行优化.在你的应用程序上运行zipalign,使得在运行时Android与应用程序间的交互更加有效率.因此,这种方式 ...
- Windows内核读书笔记——Windows异常分发处理机制
本篇读书笔记主要参考自<深入解析Windows操作系统>和<软件调试>这两本书. IDT是处理异常,实现操作系统与CPU的交互的关口. 系统在初始化阶段会去填写这个结构. ID ...