【HDU 4921】Map
来源:互联网 发布:java.io.file jar包 编辑:程序博客网 时间:2024/04/29 01:34
这道题在比赛的时候已经搞出来了大半,但是因为精度控制的不熟悉以及意识的模糊
导致最后也没有出来,赛后LL改了改细节和精度控制就过了,还是代码量太少了
首先可以注意到数据,给出的是最多不超过10条,最长不超过1000的链表
设cnt[i]为链i的长度,因此总的方案数fm=(cnt[1]+1)*(cnt[2]+1)*……*(cnt[n]+1)-1(题目要求至少取一个碎片)
则答案可以为总的几率/fm
因可以分别看两个部分,一个是所有碎片的总和,另一个是套装加成
先看第二个部分套装加成,对于每个套装加成,可先将该level存在的数给提取出来,我是放在t_val,right里面
right存放对应数的链表的右边还有多长
两个系数xishu,t_xishu分别表示
该链的个数不足i个的链的长度乘积,和该链的个数大于等于i个的链的长度乘积
因此可以枚举取法,然后t_xishu*xishu就是这个套装出现的次数,然后按照题意公式给出就行了
现在再来看第一个部分,因为我们已经枚举了所有的套装情况(除了1),因此只需要把上面说到的情况数*s,再加上只取一个链上的某一碎片的情况,就是第一部分的总和
最后一定要把两个部分先相加,再除以fm,因为多次除法会使得精度丢失非常厉害(fm估算可以到10^30)
代码如下:
#include<cstdio>#include<vector>#include<cstring>#include<algorithm>#define MM(a,b,c) memset(a,b,sizeof(a[0])*(c+2))using namespace std;const int SIZEN=10005;struct edge{ int to,next;};edge e[SIZEN];int val[SIZEN];int head[SIZEN],sz,in[SIZEN];int right[15],t_val[15];int ll,cnt,bit[1050];vector<int> num[15];double fm;void getbit(){ for(int i=1;i<1024;i++){ int ti=i; for(int j=0;j<10;j++){ bit[i]+=ti&1; ti>>=1; } }}void init(int n){ MM(head,-1,n); MM(in,0,n); sz=ll=cnt=0;}void addedge(int u,int v){ e[sz].to=v; e[sz].next=head[u]; head[u]=sz++; in[v]++;}void dfs(int u,int id){ num[id].push_back(u); for(int i=head[u];i!=-1;i=e[i].next){ int v=e[i].to; dfs(v,id); }}void rebuild(int n){ for(int i=0;i<n;i++) if(!in[i]){ num[cnt].clear(); dfs(i,cnt); ll=max(ll,(int)num[cnt].size()); cnt++; }}void debug1(){ for(int i=0;i<cnt;i++){ for(int j=0;j<num[i].size();j++) printf("%d ",num[i][j]); printf("\n"); }}double get_ans(){ fm=1; int ccnt; double xishu,t_xishu; double s,ans=0; for(int i=0;i<cnt;i++) fm*=(int)(num[i].size()+1); for(int i=0;i<ll;i++){ ccnt=0;t_xishu=1; for(int j=0;j<cnt;j++){ if(num[j].size()>=i+1){ right[ccnt]=(num[j].size()-i); t_val[ccnt++]=val[num[j][i]]; } else t_xishu*=(double)(num[j].size()+1); } for(int j=1;j<(1<<ccnt);j++){ xishu=1;s=0; int tj=j; for(int k=0;k<ccnt;k++){ if(tj&1){ xishu*=right[k]; s+=t_val[k]; } else xishu*=i+1; tj>>=1; } ans+=s*xishu*t_xishu; if(bit[j]>=2) ans+=s*xishu*t_xishu*bit[j]/ccnt; } } return ans/(fm-1);}void solve(){ int n,m; int u,v; scanf("%d%d",&n,&m); init(n); for(int i=0;i<n;i++) scanf("%d",&val[i]); for(int i=0;i<m;i++){ scanf("%d%d",&u,&v); addedge(u,v); } rebuild(n); double ans=get_ans(); printf("%.3lf\n",ans);}int main(){ int _; scanf("%d",&_); getbit(); while(_--) solve();}
0 0
- 【HDU 4921】Map
- hdu 4921 Map
- HDU 4921 Map
- hdu 4921 Map(组合计数)
- hdu 1004(map)
- hdu 1217 map+floyd
- hdu 1029 map做法
- HDU 1048 map
- hdu - 4329 - MAP - 模拟
- hdu 1004 hash map
- hdu 1004 (map)
- hdu 1075 map
- map 初学 hdu 1800
- HDU 4302 MAP应用
- HDU 2112 Map+Dijkstra
- hdu-1800(map)
- HDU 1307 map&&set
- hdu 1381 map(映射)
- 再探vim常用命令
- JSON语法
- 使用VS2012调试ReactOS源码
- [Unity3D]网游中实现资源动态加载 。。手游消减内存必备。。。
- html5的自定义data-*属性与jquery的data()方法的使用
- 【HDU 4921】Map
- Hadoop中解决跨split问题
- IOS用openurl打开设置选项 ===== 有的可能已被苹果官方禁用
- Android 实现多个输入框的对话框
- 约瑟夫环问题的详细解答
- linux oops产生过程之dump_backtrace
- 修改主机名
- 统计难题 (字典树)
- android webview的jsinterface有时候不被识别的原因