hdu 4576(简单概率dp | 矩阵优化)
艰难的一道题,体现出菜菜的我。。。
首先,先吐槽下。 这题到底出题人是怎么想的,用普通概率dp水过??? 那为什么我概率dp写的稍微烂点就一直tle? 感觉很不公平。大家算法都一致,因为我程序没有那么简练就过不了。 太坑了。。。
当然,说到底还是实力的问题,谁叫你不会一些常数级别的优化。 谁叫你写的时候不写的好一点。
比赛的时候在速度秒掉了最后两题后,卡这道题卡了4个多小时,也没有心情去看其他的题目了。 期间想了各种优化的方法。 最后因为一个小错误wa了N次后没有过而遗憾终身。。。
1. 直接 概率dp ,时间可能会很长,因为循环的次数达到了10^8次方,所以循环最内部的运算必须不能过多。 如果剩去%(这个比较费时的,话说至少是+,-的5、6倍吧)还有输入用自己定义的函数(就是不用scanf,用getchar()一个一个的读入)可以将时间缩到<2000ms
附一份普通的3000+ms的
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
using namespace std; double dp[][]; int main()
{
//freopen("//home//chen//Desktop//ACM//in.text","r",stdin);
int n,m,l,r;
while(scanf("%d%d%d%d",&n,&m,&l,&r)&&(n+m+l+r))
{
int a=,b=;
memset(dp,,sizeof(dp));
dp[a][]=;
for(int i=;i<m;i++)
{
int tmp;
scanf("%d",&tmp);
tmp%=n;
for(int j=;j<=n;j++)
{
dp[b][j]=dp[a][(j+tmp-)%n+]*0.5+dp[a][(j-tmp+n-)%n+]*0.5;
}
swap(a,b);
}
double ans=;
for(int i=l;i<=r;i++)
ans+=dp[a][i];
printf("%.4lf\n",ans);
}
return ;
}
2. 可以用矩阵优化。
首先可以知道的是这个m次运算是满足结合律的。 于是快速幂的思想就可以运用了。
统计出m次运算中 移k(1<= k <=200)位的个数。 然后这些移相同位的运算都是相同的,可以用快速幂使复杂度变成log,也就是将m次运算变成 约等于logm
构造一个矩阵,发现如果直接用矩阵乘法的话,一次相乘复杂度就达到了n*n*n也就是8*10^6 。
但是因为这题的特殊性,构造出来的矩阵对于每一列仅有的两个元素都恰好是等差错开排列的。
a b 0 a b 0 a*a 2ab b*b
0 a b * 0 a b = b*b a*a 2ab
b 0 a b 0 a 2ab b*b a*a
这里a=b=0.5 ,(还有可能a,b在同一个位置,这时只有一个a=1). 而且值得注意的时候一般有规律的矩阵乘出来的结果一般也是有规律的。
这样就可以只求出第一行的结果,然后剩余的用第一行的结果推就行了。这样复杂度就为n*n
总的复杂度是n*n*k*logm。 理论上可以接受,而且应该没有这么大,因为不可能每次进行快速幂的复杂度都达到logm。
以上有一部分引用,代码也在其中 http://www.cnblogs.com/kiwi-bird/archive/2013/08/10/3250696.html
时间大概1700+ms
3. 我自己想出来的一种类似于矩阵快速幂的方法,至少思想是这样的。 时间1400+ms
算法原理,思想都类似于快速幂,当时感觉也不是特别好就不详细解释了。
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
using namespace std; int n,m,l,r;
int save[];
double g[];
double tmp[];
double sum[]; //理论上满足结合律 int main()
{
//freopen("//home//chen//Desktop//ACM//in.text","r",stdin);
while(~scanf("%d%d%d%d",&n,&m,&l,&r)&&(n+m+l+r))
{
memset(save,,sizeof(save));
for(int i=;i<m;i++)
{
int tmp1;
scanf("%d",&tmp1);
tmp1=tmp1%n;//n就是走了0步
save[tmp1]++;
} memset(g,,sizeof(g));
g[]=;
for(int ii=;ii<n;ii++) //有save[ii] 个不同的
{
if(save[ii]==) continue;
//////////////////
int cnt;
while(save[ii])
{
cnt=;
memset(tmp,,sizeof(tmp));
tmp[ii+]=0.5;//因为ii+1可能会和n+1-ii相等所以下一步用+=是必须的
tmp[n+-ii]+=0.5; //wa 了N次在这一步. 思维还是想不到很全面
while(*cnt <= save[ii])
{
memset(sum,,sizeof(sum));
for(int i=;i<=n;i++) //从第一个位置开始
{
for(int j=;j<=n;j++)
{
int ttmp=i+j-;
if(ttmp > n) ttmp -= n;
sum[ttmp] += tmp[i]*tmp[j];
}
}
for(int i=;i<=n;i++)
tmp[i]=sum[i];
cnt=cnt+cnt;
}
memset(sum,,sizeof(sum)); for(int i=;i<=n;i++)
{
for(int j=;j<=n;j++)
{
int ttmp=i+j-;
if(ttmp>n) ttmp -= n;
sum[ttmp] += g[i]*tmp[j];//每个点对其他的贡献
}
}
for(int i=;i<=n;i++)
g[i]=sum[i]; save[ii]-=cnt;
}
} double ans=;
for(int i=l;i<=r;i++)
ans += g[i];
printf("%.4lf\n",ans);
}
return ;
}
hdu 4576(简单概率dp | 矩阵优化)的更多相关文章
- HDU 3853LOOPS(简单概率DP)
HDU 3853 LOOPS 题目大意是说人现在在1,1,需要走到N,N,每次有p1的可能在元位置不变,p2的可能走到右边一格,有p3的可能走到下面一格,问从起点走到终点的期望值 这是弱菜做的第 ...
- HDU 4576 Robot(概率dp)
题目 /*********************复制来的大致题意********************** 有N个数字,M个操作, 区间L, R. 然后问经过M个操作后落在[L, R]的概率. * ...
- HDU 4576 简单概率 + 滚动数组DP(大坑)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4576 坑大发了,居然加 % 也会超时: #include <cstdio> #includ ...
- poj3744 Scout YYF I[概率dp+矩阵优化]
Scout YYF I Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 8598 Accepted: 2521 Descr ...
- Aeroplane chess(简单概率dp)
Hzz loves aeroplane chess very much. The chess map contains N+1 grids labeled from 0 to N. Hzz start ...
- HDU - 2294: Pendant(矩阵优化DP&前缀和)
On Saint Valentine's Day, Alex imagined to present a special pendant to his girl friend made by K ki ...
- CF1151F Sonya and Informatics (计数dp+矩阵优化)
题目地址 Solution (duyi是我们的红太阳) (这里说一句:这题看上去是一个概率dp,鉴于这题的概率dp写法看上去不好写,我们其实可以写一个计数dp) 首先拿到这个题目我们要能设出一个普通d ...
- POJ 3744 Scout YYF I (概率dp+矩阵快速幂)
题意: 一条路上,给出n地雷的位置,人起始位置在1,向前走一步的概率p,走两步的概率1-p,踩到地雷就死了,求安全通过这条路的概率. 分析: 如果不考虑地雷的情况,dp[i],表示到达i位置的概率,d ...
- HDU - 1099 - Lottery - 概率dp
http://acm.hdu.edu.cn/showproblem.php?pid=1099 最最简单的概率dp,完全是等概率转移. 设dp[i]为已有i张票,还需要抽几次才能集齐的期望. 那么dp[ ...
随机推荐
- Git-Git Book阅读笔记
git diff [fname] 查看工作区与缓存区异同 git diff --staged [fname] 查看缓存区与上次提交之间的差异 git diff HEAD [fname] 查 ...
- [转]android – 多屏幕适配相关
1.基本概念 屏幕大小(screen size) – 屏幕的实际大小,用屏幕对角线长度来衡量(比如3.4寸,3.8寸).android把屏幕分为以下4种:small,normal,large,extr ...
- python 脚本(获取指定文件夹、指定文件格式、的代码行数、注释行数)
1.代码的运行结果: 获取 指定文件夹下.指定文件格式 文件的: 总代码行数.总注释行数(需指定注释格式).总空行数: #coding: utf-8 import os, re # 代码所在目录 FI ...
- Laravel自定义分页样式
<?php namespace App\Http\Controllers; use DB; use App\Http\Controllers\Controller; class UserCont ...
- unity, TRANSFORM_TEX
TRANSFORM_TEX在UnityCG.cginc中定义. ----补充: 为啥buildin shader Unlit-Normal.shader中有一个float4 _MainTex_ST变 ...
- JUC组件扩展(二)-JAVA并行框架Fork/Join(四):监控Fork/Join池
Fork/Join 框架是为了解决可以使用 divide 和 conquer 技术,使用 fork() 和 join() 操作把任务分成小块的问题而设计的.主要实现这个行为的是 ForkJoinPoo ...
- HDU 5303 Delicious Apples(思维题)
Delicious Apples Time Limit: 5000/3000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Other ...
- POJ2185-Milking Grid(KMP,next数组的应用)
Milking Grid Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 6317 Accepted: 2648 Desc ...
- 180508 - 解决有关VIVO的2018-04-01安全补丁导致的APP闪退问题
解决有关VIVO的2018-04-01安全补丁导致的APP闪退问题 [√]问题原因猜测4: 最终解决方案 [√]问题原因猜测3: 尝试解决 [√成功] [×]问题原因猜测2: 尝试解决 [×失败] [ ...
- CentOS6.x修改主机名,关闭防火墙
一.centos默认主机名为localhost,不方便管理,此次,我修改为noi. 1.修改网络配置文件:/etc/sysconfig/network 首先,备份一下源文件,注意date命令和加号之间 ...