计蒜客NOIP2017提高组模拟赛(三)day1
火山喷发
火山喷发对所有附近的生物具有毁灭性的影响。在本题中,我们希望用数值来模拟这一过程。
在环境里有 n 个生物分别具有 A1,A2,⋯,An点生命值,一次火山喷发总计 MM 轮,每轮造成 11 点伤害,等概率地分给所有存活的生物,即如果目前有 K 个活着的生物,每个生物受到这点伤害的概率是 1/K。如果一个生物的生命值减为 0,它会立即死去,此后都不会再占用受到伤害的概率。如果没有生物存活,那么将没有生物会受到伤害。
现在你的任务是,给定 n,M 和全部生物的生命值,问每个生物火山喷发后依然存活的概率。
输入格式
第一行两个正整数 n 和 M。
第二行 nn 个正整数 A_1,...,A_n。
输出格式
n 行,第 i 行一个数表示第 i 个生物存活下来的概率,保留小数点后六位。
数据范围与约定
对于 10% 的数据 N=1。
对于 30% 的数据 N=2。
对于全部数据 N≤4,M≤120,Ai≤50。
样例输入1
1 2
1
样例输出1
0.000000
样例输入2
3 15
2 12 2
样例输出2
0.001684
0.996632
0.001684
信息传递
样例输入
3 2
0 1 0
0 1 4
1 0 2
4 2 0
样例输出
0.400000
0.350000
0.250000
任性的国王
样例输入
4 14
2 3 4 3 1 1 1 5 4 7
1 1 2
1 2 3
1 1 3
1 2 4
2 1 5
1 1 4
4 2 1
1 1 3
1 2 3
1 2 4
3 3 100
1 3 4
1 2 4
1 1 4
样例输出
6
8
10
13
17
9
5
10
15
16
20
T1:
普通dp(太暴力啦)
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<string>
#define MAXN 5
using namespace std;
namespace solve1{
int a[MAXN];
void solve(int n,int m){
scanf("%d",&a[]);
double ans;
if(a[]<=m){
ans=;
printf("%.6f\n",ans);
}
else{
ans=;
printf("%.6f\n",ans);
}
}
}
namespace solve2{
int a[MAXN];
double f[][][];
void solve(int n,int m){
scanf("%d%d",&a[],&a[]);
f[][a[]][a[]]=;
for(int k=;k<=m;k++){
for(int i=;i<=a[];i++){
for(int j=;j<=a[];j++){
double t;
if(j){
t=0.5;
}
else{
t=;
}
if(i<)f[k][i][j]+=f[k-][i+][j]*t;
if(i){
t=0.5;
}
else{
t=;
}
if(j<)f[k][i][j]+=f[k-][i][j+]*t;
}
}
}
double ans1=,ans2=;
for(int i=;i<=a[];i++){
for(int j=;j<=a[];j++){
ans1+=f[m][i][j];
}
}
for(int i=;i<=a[];i++){
for(int j=;j<=a[];j++){
ans2+=f[m][i][j];
}
}
printf("%.6f\n%.6f\n",ans1,ans2);
}
}
namespace solve3{
int a[MAXN];
double f[][][][];
void solve(int n,int m){
scanf("%d%d%d",&a[],&a[],&a[]);
f[][a[]][a[]][a[]]=;
for(int k=;k<=m;k++){
for(int i=;i<=a[];i++){
for(int j=;j<=a[];j++){
for(int p=;p<=a[];p++){
double t=;
double cnt=;
if(!j) cnt=cnt-;
if(!p) cnt=cnt-;
t=t/cnt;
if(i<)f[k][i][j][p]+=f[k-][i+][j][p]*t;
t=;
cnt=;
if(!i) cnt=cnt-;
if(!p) cnt=cnt-;
t=t/cnt;
if(j<)f[k][i][j][p]+=f[k-][i][j+][p]*t;
t=;
cnt=;
if(!i) cnt=cnt-;
if(!j) cnt=cnt-;
t=t/cnt;
if(p<)f[k][i][j][p]+=f[k-][i][j][p+]*t;
}
}
}
}
double ans1=,ans2=,ans3=;
for(int i=;i<=a[];i++){
for(int j=;j<=a[];j++){
for(int p=;p<=a[];p++){
ans1+=f[m][i][j][p];
}
}
}
for(int i=;i<=a[];i++){
for(int j=;j<=a[];j++){
for(int p=;p<=a[];p++){
ans2+=f[m][i][j][p];
}
}
}
for(int i=;i<=a[];i++){
for(int j=;j<=a[];j++){
for(int p=;p<=a[];p++){
ans3+=f[m][i][j][p];
}
}
}
printf("%.6f\n%.6f\n%.6f\n",ans1,ans2,ans3);
}
}
namespace solve4{
int a[MAXN];
double f[][][][];
void solve(int n,int m){
scanf("%d%d%d%d",&a[],&a[],&a[],&a[]);
f[][a[]][a[]][a[]]=;
for(int k=;k<=m;k++){
for(int i=;i<=a[];i++){
for(int j=;j<=a[];j++){
for(int p=;p<=a[];p++){
int q=a[]-(k-(a[]-i+a[]-j+a[]-p));
if(q<) continue;
double t=;
double cnt=;
if(!j) cnt=cnt-;
if(!p) cnt=cnt-;
if(!q) cnt=cnt-;
t=t/cnt;
if(i<)f[k][i][j][p]+=f[k-][i+][j][p]*t; t=;
cnt=;
if(!i) cnt=cnt-;
if(!p) cnt=cnt-;
if(!q) cnt=cnt-;
t=t/cnt;
if(j<)f[k][i][j][p]+=f[k-][i][j+][p]*t; t=;
cnt=;
if(!i) cnt=cnt-;
if(!j) cnt=cnt-;
if(!q) cnt=cnt-;
t=t/cnt;
if(p<)f[k][i][j][p]+=f[k-][i][j][p+]*t; t=;
cnt=;
if(!i) cnt=cnt-;
if(!j) cnt=cnt-;
if(!p) cnt=cnt-;
t=t/cnt;
f[k][i][j][p]+=f[k-][i][j][p]*t;
}
}
}
}
double ans1=,ans2=,ans3=,ans4=;
for(int i=;i<=a[];i++){
for(int j=;j<=a[];j++){
for(int p=;p<=a[];p++){
ans1+=f[m][i][j][p];
}
}
}
for(int i=;i<=a[];i++){
for(int j=;j<=a[];j++){
for(int p=;p<=a[];p++){
ans2+=f[m][i][j][p];
}
}
}
for(int i=;i<=a[];i++){
for(int j=;j<=a[];j++){
for(int p=;p<=a[];p++){
ans3+=f[m][i][j][p];
}
}
} for(int i=;i<=a[];i++){
for(int j=;j<=a[];j++){
for(int p=;p<=a[];p++){
int q=a[]-(m-(a[]-i+a[]-j+a[]-p));
if(q){
ans4+=f[m][i][j][p];
}
}
}
}
printf("%.6f\n%.6f\n%.6f\n%.6f\n",ans1,ans2,ans3,ans4);
}
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
if(==n){
solve1::solve(n,m);
}
else if(==n){
solve2::solve(n,m);
}
else if(==n){
solve3::solve(n,m);
}
else{
solve4::solve(n,m);
}
return ;
}
Code1-1
其实这题可用bfs转移状态,因为按照总伤害,前面的不会对后面的产生影响,所以开始轮到队头元素时,一定是最优的
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<queue>
#define MAXN 52
using namespace std;
struct Node{
int a[];
Node(int p1=,int p2=,int p3=,int p4=){
a[]=p1,a[]=p2,a[]=p3,a[]=p4;
}
};
queue<Node> q;
double f[][][][];
bool b[][][][];
int n,m; int main()
{
int a[]={},c[]={};
scanf("%d%d",&n,&m);
for(int i=;i<n;i++){
scanf("%d",&c[i]);
}
f[c[]][c[]][c[]][c[]]=;
q.push(Node(c[],c[],c[],c[]));
while(!q.empty()){
memcpy(a,q.front().a,sizeof(a));
int sum=;
for(int i=;i<;i++){
sum+=(c[i]-a[i]);
}
if(sum>m){
break;
}
q.pop();
int cnt=;
for(int i=;i<;i++){
if(a[i]){
cnt++;
}
}
double t=/(double)cnt;
if(a[]){
f[a[]-][a[]][a[]][a[]]+=f[a[]][a[]][a[]][a[]]*t;
if(!b[a[]-][a[]][a[]][a[]]){
b[a[]-][a[]][a[]][a[]]=;
q.push(Node(a[]-,a[],a[],a[]));
}
}
if(a[]){
f[a[]][a[]-][a[]][a[]]+=f[a[]][a[]][a[]][a[]]*t;
if(!b[a[]][a[]-][a[]][a[]]){
b[a[]][a[]-][a[]][a[]]=;
q.push(Node(a[],a[]-,a[],a[]));
}
}
if(a[]){
f[a[]][a[]][a[]-][a[]]+=f[a[]][a[]][a[]][a[]]*t;
if(!b[a[]][a[]][a[]-][a[]]){
b[a[]][a[]][a[]-][a[]]=;
q.push(Node(a[],a[],a[]-,a[]));
}
}
if(a[]){
f[a[]][a[]][a[]][a[]-]+=f[a[]][a[]][a[]][a[]]*t;
if(!b[a[]][a[]][a[]][a[]-]){
b[a[]][a[]][a[]][a[]-]=;
q.push(Node(a[],a[],a[],a[]-));
}
}
}
double ans[];
if(n>=){
ans[]=;
for(int i=;i<=c[];i++){
for(int j=;j<=c[];j++){
for(int k=;k<=c[];k++){
for(int l=;l<=c[];l++){
if(c[]-i+c[]-j+c[]-k+c[]-l==m)
ans[]+=f[i][j][k][l];
}
}
}
}
}
if(n>=){
ans[]=;
for(int i=;i<=c[];i++){
for(int j=;j<=c[];j++){
for(int k=;k<=c[];k++){
for(int l=;l<=c[];l++){
if(c[]-i+c[]-j+c[]-k+c[]-l==m)
ans[]+=f[i][j][k][l];
}
}
}
}
}
if(n>=){
ans[]=;
for(int i=;i<=c[];i++){
for(int j=;j<=c[];j++){
for(int k=;k<=c[];k++){
for(int l=;l<=c[];l++){
if(c[]-i+c[]-j+c[]-k+c[]-l==m)
ans[]+=f[i][j][k][l];
}
}
}
}
}
if(n>=){
ans[]=;
for(int i=;i<=c[];i++){
for(int j=;j<=c[];j++){
for(int k=;k<=c[];k++){
for(int l=;l<=c[];l++){
if(c[]-i+c[]-j+c[]-k+c[]-l==m)
ans[]+=f[i][j][k][l];
}
}
}
}
}
for(int i=;i<n;i++){
printf("%.6f\n",ans[i]);
}
return ;
}
Code1-2
T2:
矩阵快速幂
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#define MAXN 205
using namespace std;
int n,T;
int d[MAXN][MAXN];
int sum[MAXN];
struct Mat{
double a[MAXN][MAXN];
Mat operator *= (const Mat &B){
Mat C;
for(int i=;i<=n;i++){
for(int j=;j<=n;j++){
C.a[i][j]=;
for(int k=;k<=n;k++){
C.a[i][j]+=a[i][k]*B.a[k][j];
}
}
}
memcpy(a,C.a,sizeof(a));
return *this;
}
};
void Floyed(){
for(int k=;k<=n;k++){
for(int i=;i<=n;i++){
for(int j=;j<=n;j++){
d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
}
}
}
for(int i=;i<=n;i++){
sum[i]=;
for(int j=;j<=n;j++){
sum[i]+=d[i][j];
}
}
}
int main()
{
double a[MAXN];
scanf("%d%d",&n,&T);
for(int i=;i<=n;i++){
scanf("%lf",&a[i]);
}
for(int i=;i<=n;i++){
for(int j=;j<=n;j++){
scanf("%d",&d[i][j]);
}
}
Floyed();
Mat A;
for(int i=;i<=n;i++){
for(int j=;j<=n;j++){
A.a[i][j]=(double)d[i][j]/(double)sum[j];
}
}
Mat B;
memcpy(B.a,A.a,sizeof(B.a));
T--;
while(T){
if(T&){
B*=A;
}
A*=A;
T>>=;
}
for(int i=;i<=n;i++){
double ans=;
for(int j=;j<=n;j++){
ans+=a[j]*B.a[i][j];
}
printf("%.6f\n",ans);
}
return ;
}
Code2
T3:
这题巧妙地把线段树和dp的思想结合在了一起,同时还用到了最小生成树
首先我们用f[k][i][j]表示线段树中节点k所对应区间的值,同时i表示左端的竖边是否选,j表示右端的竖边是否选
那么可以得到方程:
f[k][i][j]=min{ f[k<<1][i][1]+f[k<<1|1][1][j]-cot[mid], f[k<<1][i][1]+f[k<<1|1][0][j]-cot[mid], f[k<<1][i][0]+f[k<<1|1][1][j]-cot[mid] }
其中cot[mid]表示中间的竖边
证明如下:
(1)如果最小生成树中包含竖边mid
那么左区间和右区间内包含mid的最小生成树合并一定可以得到最优解
(2)如果最小生成树不包含竖边mid
那么由于图是连通的,那么一定存在一条竖边,它要么位于左区间,要么位于右区间(要么两边都有)
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#define MAXN 100005
#define INF 1000000000
using namespace std;
int a[MAXN];
int f[MAXN*][][];
int n;
int up[MAXN],down[MAXN],cot[MAXN];
int read(){
int x=;char ch=getchar();
while(ch<''||ch>''){ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x;
}
void pushup(int k,int c){
int lc=(k<<),rc=(k<<|);
for(int i=;i<;i++){
for(int j=;j<;j++){
int t=INF;
t=min(t,f[lc][i][]+f[rc][][j]-c);
t=min(t,f[lc][i][]+f[rc][][j]-c);
t=min(t,f[lc][i][]+f[rc][][j]-c);
f[k][i][j]=t;
}
}
}
void build(int k,int L,int R){
if(L+==R){
f[k][][]=INF;
f[k][][]=up[L]+down[L]+cot[L+];
f[k][][]=up[L]+down[L]+cot[L];
f[k][][]=min(up[L],down[L])+cot[L]+cot[L+];
return ;
}
build(k<<,L,(L+R)>>);
build(k<<|,(L+R)>>,R);
pushup(k,cot[(L+R)>>]);
}
void ask(int a,int b,int k,int L,int R,int &q00,int &q01,int &q10,int &q11){
if(a<=L&&R<=b){
q00=f[k][][];
q01=f[k][][];
q10=f[k][][];
q11=f[k][][];
return;
}
else{
int mid=((L+R)>>);
if(b<=mid){
ask(a,b,k<<,L,mid,q00,q01,q10,q11);
return;
}
if(a>=mid){
ask(a,b,k<<|,mid,R,q00,q01,q10,q11);
return;
}
int c=cot[mid];
int p00,p01,p10,p11,l00,l01,l10,l11;
ask(a,b,k<<,L,mid,p00,p01,p10,p11);
ask(a,b,k<<|,mid,R,l00,l01,l10,l11); int t=INF;
t=min(t,p01+l10-c);
t=min(t,p01+l00-c);
t=min(t,p00+l10-c);
q00=t; t=INF;
t=min(t,p01+l11-c);
t=min(t,p01+l01-c);
t=min(t,p00+l11-c);
q01=t; t=INF;
t=min(t,p11+l10-c);
t=min(t,p11+l00-c);
t=min(t,p10+l10-c);
q10=t; t=INF;
t=min(t,p11+l11-c);
t=min(t,p11+l01-c);
t=min(t,p10+l11-c);
q11=t;
}
}
void update(int a,int k,int L,int R,int x,int K){
if(L+==R){
if(==K){
up[a]=x;
}
else if(==K){
down[a]=x;
}
else{
cot[a]=x;
}
f[k][][]=INF;
f[k][][]=cot[L]+up[L]+down[L];
f[k][][]=cot[L+]+up[L]+down[L];
f[k][][]=cot[L]+cot[L+]+min(up[L],down[L]);
return;
}
int mid=((L+R)>>);
if(mid>=a){
update(a,k<<,L,mid,x,K);
}
if(mid<=a){
update(a,k<<|,mid,R,x,K);
}
pushup(k,cot[mid]);
}
int main()
{
//freopen("data.in","r",stdin);
n=read();
int T=read();
for(int i=;i<n;i++){
up[i]=read();
}
for(int i=;i<n;i++){
down[i]=read();
}
for(int i=;i<=n;i++){
cot[i]=read();
}
build(,,n+);
for(int i=;i<=T;i++){
int K=read(),S=read(),T=read();
if(==K){
if(S==T){
printf("%d\n",cot[S]);
}
else{
int q00,q01,q10,q11;
ask(S,T,,,n+,q00,q01,q10,q11);
printf("%d\n",min(min(q00,q01),min(q10,q11)));
}
}
else{
update(S,,,n+,T,K);
}
}
return ;
}
Code3
计蒜客NOIP2017提高组模拟赛(三)day1的更多相关文章
- 计蒜客NOIP2017提高组模拟赛(四)day1
T1:小X的质数 小 X 是一位热爱数学的男孩子,在茫茫的数字中,他对质数更有一种独特的情感.小 X 认为,质数是一切自然数起源的地方. 在小 X 的认知里,质数是除了本身和 1 以外,没有其他因数的 ...
- 计蒜客NOIP2017提高组模拟赛(五)day1-展览
传送门 发现这题选或不选对状态的优劣程度不会产生影响,如果已经确定了两个数a和b,那么最优的首项和公比也都是唯一确定的, 与对于后面的数x,加进去也好不加进去也好,首项和公比依旧是原来的 于是我们用尺 ...
- 计蒜客NOIP2017提高组模拟赛(五)day1-机智的 AmyZhi
传送门 很水的题目啦QAQ #include<cstdio> #include<cstdlib> #include<algorithm> #include<c ...
- 计蒜客NOIP2017提高组模拟赛(五)day2-蚂蚁搬家
传送门 这题可以用线段树来维护 #include<cstdio> #include<cstdlib> #include<algorithm> #include< ...
- 计蒜客NOIP2017提高组模拟赛(五)day2-成绩统计
传送门 用hash,因为map的复杂度可能在这题中因为多一个log卡掉,但是hash不会 可能因为这个生成的随机数有循环的情况,不是完全均匀的 而且这题hash表的长度也可以开的很大 #include ...
- 计蒜客NOIP2017提高组模拟赛(三)day2-数三角形
传送门 这题有点坑啊 设A为两边颜色不同的角,B为两边颜色相同的角 那么考虑三种三角形:异色,同色,其他 对于任何一个异色三角形,一定会有三个颜色不同的角, 对于任何一个同色三角形,一定会有零个颜色不 ...
- 计蒜客NOIP2017提高组模拟赛(三)day2-直线的交点
传送门 简单几何+逆序对 发现当两条直线甲乙与平板的交点在上面甲在较左的位置,那么下面甲在较右的位置就可以相交 然后把上面的位置排下序,下面离散化+树状数组即可 #include<cstdio& ...
- 计蒜客NOIP2017提高组模拟赛(三)day2-小区划分
传送门 dp,注意边界 #include<cstdio> #include<cstdlib> #include<algorithm> #include<cst ...
- 计蒜客 NOIP 提高组模拟竞赛第一试 补记
计蒜客 NOIP 提高组模拟竞赛第一试 补记 A. 广场车神 题目大意: 一个\(n\times m(n,m\le2000)\)的网格,初始时位于左下角的\((1,1)\)处,终点在右上角的\((n, ...
随机推荐
- 20162318 实验二《Java面向对象程序设计》实验报告
北京电子科技学院(BESTI) 实 验 报 告 课程:程序设计与数据结构 班级:1623班 姓名:张泰毓 指导老师:娄老师.王老师 实验日期:2017年4月14日 实验密级:非密级 实验器材:带Lin ...
- 网页设计入门<一>
俗话说:技多不压身.实习周,网页设计是之一,边学边总结... 本次网页设计基于Adobe Dreamweaver CS6开发平台,根据实习老师的暴力指导,为什么说暴力呢? 没有基础,没有预告,打开软件 ...
- 《高级软件测试》11.15.全组完成jira安装,开始任务的部分书写
今日任务完成情况如下: 小段:完成linux环境上jira的安装,并将jira的安装过程录制下来 小费:完成linux环境下jira的安装,开始部分任务的书写 小高:完成了jira的安装,并进一步熟悉 ...
- 火车头采集器对接织梦cms图集发布时, 采集网上图片超时的解决方法
背景介绍: 火车头采集器对接织梦cms图片集发布时, 对于多张(超过30张)大图片时, 经常会出现图集发布超时的情况. 问题分析: 因为php对于资源的处理有默认的超时时间30秒, 而我尝试了好多方 ...
- Python爬虫之urllib模块1
Python爬虫之urllib模块1 本文来自网友投稿.作者PG,一个待毕业待就业二流大学生.玄魂工作室未对该文章内容做任何改变. 因为本人一直对推理悬疑比较感兴趣,所以这次爬取的网站也是平时看一些悬 ...
- Spring中报"Could not resolve placeholder"的解决方案
除去properites文件路径错误.拼写错误外,出现"Could not resolve placeholder"很有可能是使用了多个PropertyPlaceholderCon ...
- SQL查询语句练习
最近在学习SQL嘛,所以各个地方找题目来练手,毕竟现在能离得开数据库么? Student(S#,Sname,Sage,Ssex) 学生表 Course(C#,Cname,T#) 课程表 SC(S#,C ...
- win7远程桌面 连接不上(用户名与全名不匹配的问题)
用户名与用户全名不一致导致的.我刚也是这个问题,折腾够了好久.你先看看 计算机右键→管理→本地用户和组→用户 找到你需要远程的管理员账户,看看名称与全名是否一致,若不一致,继续看下面.1.按" ...
- 告知服务器意图的http方法
1.GET 用来获取资源,返回已有的结果 2.POST 传输实体主体,返回处理过后的结果 3.PUT 向服务器传输文件,返回是否成功的状态码 4.DELETE 删除服务器文件,返回是否成功的状态码 5 ...
- nginx 官方文档翻译
nginx(发音为"engine x")是一个由俄罗斯软件工程师Igor Sysoev编写的免费开源Web服务器.自2004年公开发布以来,nginx专注于高性能,高并发性和低内存 ...