題目描述:知道n+1(包括Oliver)我的的語文、數學、英語成績,求出Oliver的數學、語文、英語分別和最高的分數差多少?ios
思路:高精+排序
考試一瞟數據最長的成績<30位,便無奈至極,因而手動碼起了高精
由於他只用求出與最大的分差,因此能夠用排序,將三科的最大成績求出來
再作三次高精減就能夠A了
時間複雜度O(3*30+3nlogn)markdown
代碼:學習
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.
題目描述:有一棵技能樹,每一個節點都是一個技能,學習一個技能,才能學會它的後繼技能,每項技能都有不一樣的等級,不一樣的等級耗不一樣的技能點,和擁有不一樣的分數。要求出最大的分數ui
思路:樹形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]spa
代碼:code
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.
題目描述:用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
breakinput
代碼:數學
#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;
}
題目描述:有一串珠子,每一個珠子有一個能量值E[i],除了先後兩個珠子,其餘的都符合Ei=(Ei-1+Ei+1)/2+Di,如今知道所有Di、E1和En,讓你求出E2~E(n-1)string
思路:數學
知道: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(第一) 此次,考得還算能夠,明天繼續保持(∩_∩)