2014(高斯消元 DP 数论)Multi-University Training Contest 1 题解

来源:互联网 发布:一卡通流量软件 编辑:程序博客网 时间:2024/06/05 04:22

http://blog.sina.com.cn/s/blog_6bddecdc0102uy9g.html

A.Couple doubi(hdu 4861):



#include<stdio.h>int main(){    int k,p;    while(~scanf("%d %d",&k,&p)){        int num=k/(p-1);        if(num%2==0) printf("NO\n");        else printf("YES\n");    }    return 0;}


D.Task(hdu 4864)

基本思想是贪心。

价值c=500*time+2*level,level最大影响100*2<500.所以近似求time最大,可以先对任务按照时间大到小排序(时间相等时按照等级由大到小排序)。从最大时间的任务开始,找出满足任务时间要求的所有机器,从中找出满足等级最低且满足等级要求的机器与之匹配。依次对任务寻找满足要求的机器(能匹配当前的任务,那么剩下的所有的任务都是能匹配到的,那么这个机器一定会被用掉,当然选价值最大的。最大匹配数无论如何都会加1,如果不选当前的任务,那么剩下的机器中可能没有能完成该任务的了。而其他任务在剩下的机器中还可能得到匹配)


#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;#define TIME 1449#define LEVEL 109#define MAX 100009struct Node {    int time;    int level;} task[MAX],mach[MAX];int map[TIME][LEVEL];bool cmp(struct Node a, struct Node b){    if(a.time==b.time) return a.level > b.level;    return a.time > b.time;}int main() {    int n,m;    while(~scanf("%d %d",&n,&m)) {        memset(map,0,sizeof(map));        for(int i=0; i<n; i++) {            scanf("%d %d",&mach[i].time,&mach[i].level);            map[mach[i].time][mach[i].level]++;        }        for(int i=0; i<m; i++) {            scanf("%d %d",&task[i].time,&task[i].level);        }        sort(task,task+m,cmp);        __int64 ans=0,cnt=0;        bool ok=false;        for(int i=0; i<m; i++) {            ok=false;            for(int t=task[i].level; t<LEVEL; t++) {                for(int j=task[i].time; j<TIME; j++) {                    if(map[j][t]!=0) {                        cnt++;                        map[j][t]--;                        ans+=(__int64)(500*task[i].time+2*task[i].level);                        ok=true;                        break;                    }                }                if(ok==true) break;            }        }        printf("%I64d %I64d\n",cnt,ans);    }    return 0;}/***1 2300 3100 2200 1***/

E.Peter's Hobby(hdu 4865)

类型:dp

本题的题意是:给出n天的叶子的湿度,让你求出天气最有可能出现的序列。

叶子湿度序列:{b1,b2...bn},若天气序列为: {a1,a2....an},则该序列的概率应为:

f[a1]*wh[a1][b1]* ww[a1][a2] *wh[a2][b2]* ww[a2][a3]* wh[a3][b3]*........*ww[an-1][an]*wh[an][bn];

最后选择概率最大的序列即可。

由于概率的值非常小,同过log把乘法变成加法,减少精度的损失。


#include<stdio.h>#include<string.h>#include <math.h>#include<algorithm>using namespace std;#define eps 1e-7const int N=100005;double f[20050][5];int pre[20050][5];double d[3][3]= {    {0.5 ,0.375,0.125},    {0.25,0.125,0.625},    {0.25,0.375,0.375}};double p[3][4]= {    {0.6 ,0.2 ,0.15,0.05},    {0.25,0.3,0.2,0.25},    {0.05,0.10,0.35,0.50}};char ss[3][8]= {"Sunny","Cloudy","Rainy"};int check(char *s) {    if(strcmp(s,"Dry")==0)  return 0;    if(strcmp(s,"Dryish")==0)  return 1;    if(strcmp(s,"Damp")==0)  return 2;    if(strcmp(s,"Soggy")==0)  return 3;    return 0;}void output(int time,int k){    if(time==0) return;    output(time-1,pre[time][k]);    printf("%s\n",ss[k]);}int main() {    int T,n;    char str[100];    while(~scanf("%d",&T)) {        for(int cas=1; cas<=T; cas++) {            printf("Case #%d:\n",cas);            scanf("%d",&n);            f[1][0]=0.63;            f[1][1]=0.17;            f[1][2]=0.20;            for(int i=1; i<=n; i++ ) {                scanf("%s",str);                int k=check(str);                for(int j=0; j<3; j++) {                    if(i==1) {                        f[i][j]=log(f[i][j])+log(p[j][k]);                    } else {                        f[i][j]=-100000;                        for(int t=0; t<3; t++) {                            if(f[i][j]<f[i-1][t]+log(d[t][j])+log(p[j][k])) {                                f[i][j]=f[i-1][t]+log(d[t][j])+log(p[j][k]);                                pre[i][j]=t;                            }                        }                    }                }                memset(str,0,sizeof(str));            }            int k=0;            if(f[n][1]>f[n][k]) k=1;            if(f[n][2]>f[n][k]) k=2;            output(n,k);        }    }    return 0;}


I. Turn the pokers(hdu 4869)

http://www.cnblogs.com/sayeter/p/3864184.html

由于mod=10^9这么大,f[MAX]我竟然用了int,调了很久才知道是这个地方错了,用long long int(10^18)刚刚好

#include<stdio.h>#define MAX 100009#define mod 1000000009int n,m,x;long long int f[MAX];void deal(){    f[0]=1;    for(int i=1;i<MAX;i++){        f[i]=(f[i-1]*i)%mod;    }}long long quick_mod(long long a,long long b){    long long ans=1;    while(b){        if(b&1){            ans=(ans*a)%mod;            b--;        }        b=b/2;        a=a*a%mod;    }    return ans;}int main(){    deal();    while(~scanf("%d %d",&n,&m)){        int s=0,e=0,S,E;        for(int i=0;i<n;i++){            scanf("%d",&x);            if(x<=s) S=s-x;            else if(x<=e) S=((s%2)==(x%2)?0:1);            else S=x-e;            if(x+e<=m) E=e+x;            else if(x+s<=m) E=((x+s)%2==(m%2)?m:m-1);            else E=2*m-(x+s);            s=S;            e=E;        }        long long ans=0;        for(int i=S;i<=E;i+=2){            ans=ans+(f[m]*quick_mod((f[m-i]*f[i])%mod,mod-2))%mod;            ans=ans%mod;        }        printf("%lld\n",ans);    }return 0;}/***2 4335 43s=8 e=8 S=8 E=81450085135 4646 10 45 43 10s=22 e=46 S=22 E=465569290282 3210 32s=22 e=22 S=22 E=22645122405 4747 33 27 46 45s=10 e=44 S=10 E=4441816979013 5050 1 4 5 7 8 2 3 4 5 1 2 2s=6 e=50 S=6 E=50948123245****

Rating (hdu 4870)

//http://www.cnblogs.com/luyingfeng/p/3864693.html/**题意:有两个号,初始分数都是0,每次选一个分数较小的打比赛,如果分数一样任选一个,有p的概率涨50分,最高为1000分,有1-p的概率跌100分,最低为0分。问有一个号涨到1000需要打比赛的次数的期望。令(x, y)表示高分为x,低分为y的状态(x >= y),E(x, y)表示从(x, y)到达(1000, ?)的比赛场数期望。容易得到E(x, y) = P * E(x1, y1) + (1 - P) * E(x2, y2) + 1,其中,(x1, y1)表示rating上升后的状态,(x2, y2)表示rating下降后的状态。每50分一个状态,共有210个状态。移项后得E(x, y) -P * E(x1, y1) - (1 - P) * E(x2, y2) = 1,共有210个这样的方程组。高斯消元求解,x[0]代表E(0,0)这个状态到目标状态的期望。 注意精度。*/#include <stdio.h>#include <string.h>#include <iostream>#include <math.h>using namespace std ;const double eps = 1e-9 ;double p,mp[250][250];// mp数组中mp[i]表示第i个方程组 int vis[25][25] ;//表示分数为E(i,j)的这个变量对应的编号 double Gauss() {//消元完成后,只有对角线上和最后一列会有系数,其他的地方全为零。     for(int i = 0 ; i < 210 ; i++) {        int k ;        for(k = i ; k < 210 ; k++)            if(fabs(mp[k][i]) > eps) break ;//用第i列不为零的行(>=i的行),进行消元         for(int j = 0 ; j <= 210 ; j++)            swap(mp[i][j],mp[k][j]) ;        for(int j = 0 ; j < 210 ; j++) {            if(i != j) {                if(fabs(mp[j][i]) > eps) {//防止除数为零                     double s = mp[j][i] / mp[i][i] ;                    for(int k = i ; k <= 210 ; k++)                        mp[j][k] -= mp[i][k] * s ;                }            }        }    }    return mp[0][210]/mp[0][0] ;//mp[0][210]为:a1*x1+a2*x2+....an*xn=b1;中的b1,那么mp[0][210]/mp[0][0]即为E[0][0]的值了 }/***E(x,y)中(x>=y&&x>=0&&x<=20&&y>=0&&y<=19)那么这样的组合刚好有(21*20)/2这么多个变量,则需要建210个方程来解 同时:状态中不用计入状态(1000,?)是因为除了(1000,950)外其他状态不会出现。而(1000,950)状态只与状态(950,950)有关并且(950,950)不会从(1000,950)得到,210个状态中没有状态是与(1000,?)状态相关,所以不需要处理。(E(1000,?)==0)*/void pro() {//该函数用于构造非齐次线性方程组的增广矩阵(系数阵+常数阵)     for(int i = 0 ; i < 20 ; i++) {        for(int j = 0 ; j < i ; j ++) {            int u = vis[i][j] ;            mp[u][u] = 1 ;            mp[u][210] = 1 ;            int v = vis[i][max(0,j-2)] ;            mp[u][v] -= (1-p) ;//找到对应的变量E(u,v)在mp[u]这个方程中的位置             v = vis[i][j+1] ;            mp[u][v] -= p ;        }        int u = vis[i][i] ;        mp[u][u] = 1 ;        mp[u][210] = 1 ;        int v = vis[i][max(0,i-2)] ;        mp[u][v] -= (1-p) ;        v = vis[i+1][i] ;        mp[u][v] -= p ;    }}int main() {    while(scanf("%lf",&p) != EOF) {        int cnt = 0 ;        memset(vis,-1,sizeof(vis)) ;        for(int i = 0 ; i < 20  ; i++)            for(int j = 0 ; j <= i ; j++)                vis[i][j] = cnt ++ ;        for(int i=0; i<20; i++) {            for(int j=0; j<=i; j++) {                printf("%d ",vis[i][j]);            }            puts("");        }        memset(mp,0,sizeof(mp)) ;        pro() ;        printf("%.6lf\n",Gauss()) ;    }    return 0 ;}


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 幼儿园安全教案迷路了怎么办及反思 老婆发现我出轨后离家出走了怎么办 把丝袜放进马桶水箱堵了怎么办 如果老公那方面不行但人很好怎么办 老公哪里都好就是那方面不行怎么办 电饭锅盖子卡的地方掉了怎么办 唯品会退货已经收到了不退款怎么办 有人用qq冒充我和别人聊天怎么办 别人冒充我的微信名和头像怎么办 快餐店无证经营被工商局查了怎么办 买的圣才电子书只有在线版怎么办 吃了汤汤水水奶水还是少怎么办 粗肋草叶子和劲长白点怎么办 海鲜泡的时间长了有味了怎么办 富贵竹新长出来的叶子发黄怎么办 家里养的竹子的叶子发黄怎么办 发财树叶子发黄发黑怎么办打蔫 装修公司把衣柜型号弄错了怎么办 隔水炖锅里的陶瓷坏了怎么办? 色选大米带出比大怎么办? 做手足印如果漆刷到外面了怎么办 小区房子整租给民工影响邻居怎么办 种植牙植体中间的螺丝滑丝怎么办 宝宝1岁了牙齿表面脱落了怎么办 1岁3个月宝宝牙齿发黑脱落怎么办 种植牙中央螺栓断在牙根里怎么办 欧联杯冠军已经获得欧冠资格怎么办 孩子该上学了学校不收怎么办 帮室友带东西她忘给钱怎么办? 鸿合录播系统不会自动跟踪了怎么办 小米2s锁屏密码忘了怎么办 想用中国驾照去美国开车怎么办? 5座的车坐7个人怎么办 海尔电视机的设置调乱了怎么办 老公弟兄两个有个偏心的婆婆怎么办 农商银行u盾密码忘了怎么办 不熟的表弟表妹向你借钱怎么办 开货车撞到人家房子了怎么办 坐骨被摔跤后好多年没好怎么办 自动挡汽车电子手刹刹车失灵怎么办 买家拍了不包邮的宝贝付款了怎么办