2017.7.11 C组总结
来源:互联网 发布:电脑gif制作软件 编辑:程序博客网 时间:2024/06/08 12:23
NO.1
题目描述:知道n+1(包括Oliver)个人的语文、数学、英语成绩,求出Oliver的数学、语文、英语分别和最高的分数差多少?
思路:高精+排序
考试一瞟数据最长的成绩<30位,便无奈至极,于是手动码起了高精
因为他只用求出与最大的分差,所以可以用排序,将三科的最大成绩求出来
再做三次高精减就可以A了
时间复杂度O(3*30+3nlogn)
代码:
uses math;const maxn=30;type arr=array[0..10001]of string;var x1,y1,z1:string; x,y,z:array[0..10001]of string; n,i:longint;procedure qsort(var x:arr;l,r:longint);var i,j:longint; mid:string;begin if l>=r then exit; i:=l; j:=r; mid:=x[(l+r) div 2]; repeat while (length(x[i])=length(mid))and(x[i]>mid)or(length(x[i])>length(mid)) do inc(i); while (length(x[j])=length(mid))and(x[j]<mid)or(length(x[j])<length(mid)) do dec(j); if i<=j then begin x[0]:=x[i]; x[i]:=x[j]; x[j]:=x[0]; inc(i); dec(j); end; until i>j; qsort(x,l,j); qsort(x,i,r);end;procedure jian(x,y:string);var i,g,l:longint; l1,l2,l3:array[0..30]of longint;begin fillchar(l1,sizeof(l1),#0); fillchar(l2,sizeof(l2),#0); fillchar(l3,sizeof(l3),#0); for i:=1 to length(x) do l1[maxn-length(x)+i]:=ord(x[i])-48; for i:=1 to length(y) do l2[maxn-length(y)+i]:=ord(y[i])-48; for i:=maxn downto 1 do begin g:=l1[i]; if g<l2[i] then begin l1[i-1]:=l1[i-1]-1; g:=g+10; end; g:=g-l2[i]; l3[i]:=g mod 10; end; l:=1; while (l3[l]=0)and(l<=maxn) do inc(l); for i:=l to maxn do write(l3[i]); write(' ');end;begin assign(input,'score.in'); assign(output,'score.out'); reset(input); rewrite(output); readln(x1); readln(y1); readln(z1); readln(n); for i:=1 to n do begin readln(x[i]); readln(y[i]); readln(z[i]); end; qsort(x,1,n);if (length(x1)=length(x[1]))and(x1>=x[1])or(length(x1)>length(x[1])) then write('0 ') else jian(x[1],x1); qsort(y,1,n);if (length(y1)=length(y[1]))and(y1>=y[1])or(length(y1)>length(y[1])) then write('0 ') else jian(y[1],y1); qsort(z,1,n);if (length(z1)=length(z[1]))and(z1>=z[1])or(length(z1)>length(z[1])) then write('0 ') else jian(z[1],z1); close(input); close(output);end.
NO.2
题目描述:有一棵技能树,每个节点都是一个技能,学习一个技能,才能学会它的后继技能,每项技能都有不同的等级,不同的等级耗不同的技能点,和拥有不同的分数。要求出最大的分数
思路:树形DP+模拟
乍一看,1<=n<=20,便想到搜索,旁边的黄大佬便码起了搜索,结果只有20!!!
听了dalao的讲解,
首先,设l1[i][j]表示为第i个技能j级的位置(即输入顺序)
设a[i][0]表示技能i的前继技能和上一级的个数
a[i][j]表示技能i的第j级的前继技能和上一级的位置
要求出对于任何一个结点的后继结点和前继结点、相应的技能点(f[i])和分数(w[i])
然后,对于i的父亲名字==j的名字(就是j是i的前继技能),那么a[l1[j][1]][0]++,a[l1[++y,1],a[l1[y,1],0]]=l1[i,1](就是求出对于i结点的前继技能)
于是要造一棵树,表示对于每个结点的要学的两个端点(也就是说对于i结点要学的技能就在[l..r]这个区间内)
设dp[i][j]表示为从i出发,用了j技能点的最大分数值,那么状态转移方程就是dp[x][i]=max(dp[r[x]][i],dp[l[x]][j]+dp[r[x]][i-j-f[x]]+w[x])
0<=i<=p,1<=j<=i-f[x]
代码:
uses math;var n,m,x,y,s,root,p,i,j:longint; l1:array[0..20,0..20]of longint; l,r,f,w:array[0..400]of longint; a:array[0..400,0..400]of longint; dp:array[-1..400,0..100]of longint; name,fname:array[0..20]of string;procedure build(x:longint);var i:longint;begin for i:=1 to a[x,0]-1 do r[a[x,i]]:=a[x,i+1]; if (a[x,0]>0) then l[x]:=a[x,1]; for i:=1 to a[x,0] do build(a[x,i]);end;procedure treedp(x:longint);var i:longint;begin if x=-1 then exit; treedp(l[x]); treedp(r[x]); for i:=0 to p do begin dp[x,i]:=dp[r[x],i]; for j:=0 to i-f[x] do dp[x,i]:=max(dp[x,i],dp[l[x],j]+dp[r[x],i-j-f[x]]+w[x]); end;end;begin assign(input,'skill.in'); assign(output,'skill.out'); reset(input); rewrite(output); readln(n); for i:=1 to n do begin readln(name[i]); readln(fname[i]); readln(s); for j:=1 to s do begin inc(x); l1[i,j]:=x; read(y); f[x]:=y; if j>1 then begin inc(a[l1[i,j-1],0]); a[l1[i,j-1],a[l1[i,j-1],0]]:=l1[i,j]; end; end; readln; for j:=1 to s do begin read(y); w[l1[i,j]]:=y; end; readln; end; for i:=1 to n do begin y:=root; for j:=1 to n do if (fname[i]=name[j]) then begin y:=j; break; end; inc(a[l1[y,1],0]); a[l1[++y,1],a[l1[y,1],0]]:=l1[i,1]; end; readln(p); for i:=1 to n do begin read(y); for j:=1 to y do begin w[l1[i][j]]:=0; f[l1[i][j]]:=0; end; end; for i:=0 to x do begin l[i]:=-1; r[i]:=-1; end; build(root); treedp(root); writeln(dp[root,p]); close(input); close(output);end.
NO.3
题目描述:用m个人n个物品,每个人的背包是无限大的,但是每件物品在每个背包只能装一个,而且每个背包都不完全相同,问最大的物品价值和是多少
思路:贪心+递推
因为每件物品在每个背包只能装一个,那么设f[i]来表示分数值为i的情况有多少种
递推式就是f[i]=f[i-w[i]]+f[i]
然后downto,用贪心得出最大可能性ans,这里的贪心有两种操作:
①如果f[i]<=m
ans=ans+i*f[i];
m=m-f[i]
②如果f[i]>m
ans=ans+i*m
break
代码:
#include<cstdio>#include<iostream>using namespace std;unsigned long long ans,sum=0,f[25100];long n,m,w[510];int main(){ freopen("team.in","r",stdin); freopen("team.out","w",stdout); scanf("%d%d",&m,&n); for (int i=1;i<=n;i++) { scanf("%d",&w[i]); sum=sum+w[i]; } f[0]=1; for (int i=1;i<=n;i++) { for (int j=sum;j>=0;j--) if (j>=w[i]) f[j]+=f[j-w[i]]; } ans=0; for (int i=sum;i>=0;i--) if (f[i]<=m) { m-=f[i]; ans=ans+f[i]*i; } else { ans=ans+i*m; break; } printf("%lld",ans); fclose(stdin); fclose(stdout); return 0;}
NO.4
题目描述:有一串珠子,每个珠子有一个能量值E[i],除了前后两个珠子,其他的都符合Ei=(Ei-1+Ei+1)/2+Di,现在知道全部Di、E1和En,让你求出E2~E(n-1)
思路:数学
知道:2E2-E1-E3=2D2 ①
2E3-E2-E4=2D3 ②
2E4-E3-E5=2D4 ③
……
然后,②*2-① 3E3-2E4=E1+2D2+4D3
③*3-② 4E4-3E5=E1+2D2+4D3+6D4
……
可以得到规律k*Ek-(k-1)*Ek+1=E1+2D2+4D3+…+(k-1)*2*Dk
把n-1当k代入得(N-1)*EN-1-(N-2)*EN=E1+2D2+4D3+…+(N-2)*2*DN-1
然后就可以发现这个式子里只有一个未知数,直接求就好了
代码:
#include<cstdio>#include<iostream>using namespace std;long long n,e[500000],a[500000],d[500000];int main(){ freopen("fett.in","r",stdin); freopen("fett.out","w",stdout); scanf("%lld%lld",&n,&e[1]); scanf("%lld",&e[n]); for (int i=2;i<=n-1;i++) scanf("%lld",&d[i]); a[2]=0; a[3]=(a[2]-d[2])*2-e[1]; for (int i=4;i<=n;i++) a[i]=(a[i-1]-d[i-1])*2-a[i-2]; e[2]=(e[n]-a[n])/(n-1); for (int i=3;i<=n;i++) e[i]=(e[i-1]-d[i-1])*2-e[i-2]; for (int i=1;i<=n;i++) printf("%lld ",e[i]); fclose(stdin); fclose(stdout); return 0;}
这次比赛,100(高精)+0+100(递推+贪心)+100(手动推公式)=300(第一)
这次,考得还算可以,明天继续保持(∩_∩)
- 2017.7.11 C组总结
- 2017.7.6 C组总结
- 2017.7.7 C组总结
- 2017.7.8 C组总结
- 2017.7.9 C组 总结
- 2017.7.10 C组总结
- 2017.7.12 C组总结
- 2017.7.13 C组总结
- 2017.7.14 C组总结
- 2017.7.15 C组总结
- 16.8.11 C组总结
- 16.7.16 C组总结
- C组7.16题解&总结
- 16.7.17 C组总结
- 16.8.12 C组总结
- 16.8.13 C组总结
- 16.8.14 C组总结
- 2016.8.15 C组总结
- MySQL系列—MySQL程序介绍
- Python3.6 安装Scrapy
- Java反射机制的应用-模拟Spring的依赖注入
- nyoj-1112-求次数
- 洛谷P1005 矩阵取数游戏
- 2017.7.11 C组总结
- 【2015.10.17普及模拟】Oliver的成绩(score)
- C++中利用迭代器删除元素会发生什么?
- ASP.Net 学习路线
- Oracle无法启动监听方法
- C++多态性
- 卡方分布(Chi-square Distribution)
- maven入门
- POJ