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.
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 ;}
- 2014(高斯消元 DP 数论)Multi-University Training Contest 1 题解
- 2014 Multi-University Training Contest 1 题解
- 2014 Multi-University Training Contest 1/HDU4861_Couple doubi(数论/规律)
- 2014 Multi-University Training Contest 7 题解
- 2014 Multi-University Training Contest 8题解
- Hdu4952 - Number Transformation - 数论(2014 Multi-University Training Contest 8)
- 【数论】2015 Multi-University Training Contest 1 1001
- (HDU 5728)2016 Multi-University Training Contest 1 PowMod(数论)
- HDU 4870 Rating 2014 Multi-University Training Contest 1 J题 概率DP+高斯消元
- 2014 Multi-University Training Contest 1小记
- 2014 Multi-University Training Contest 1
- 2014 Multi-University Training Contest 1
- 2014 Multi-University Training Contest 1
- 2014 Multi-University Training Contest 1
- 2014 Multi-University Training Contest 1
- 2014 Multi-University Training Contest 9 题解&&总结
- 2015 Multi-University Training Contest 1 题解 BY FZUw
- 2015 Multi-University Training Contest 1 题解&&总结
- JS实现全景图效果360度旋转
- ntelliJ IDEA12的解决占用C盘C:\Users\Administrator
- 如何添加/usr/local/lib/的库文件
- 人工砂的技术开发制造设备
- 百度拾取坐标系统
- 2014(高斯消元 DP 数论)Multi-University Training Contest 1 题解
- 二进制和位运算中的异或
- 用Eclipse+Maven+Jetty构建Java Web开发环境(综合几篇教程整合2014年版)
- linux shell 自定义函数(定义、返回值、变量作用域)介绍
- java 新进程(ProcessBuilder) 远程(Ganymed SSH-2)
- hdoj Task
- 产品回顾本讲谈社汉字学习词典(kald)对于卡西欧EX-字的DataPlus系列
- Web项目使用之jqGrid-实用
- Java 遍历文件夹获得全部文件(或者按照扩展名打印)