2017.7.11 C組總結

NO.1

題目描述:知道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.

NO.2

題目描述:有一棵技能樹,每一個節點都是一個技能,學習一個技能,才能學會它的後繼技能,每項技能都有不一樣的等級,不一樣的等級耗不一樣的技能點,和擁有不一樣的分數。要求出最大的分數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.

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
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;
}

NO.4

題目描述:有一串珠子,每一個珠子有一個能量值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(第一) 此次,考得還算能夠,明天繼續保持(∩_∩)

相關文章
相關標籤/搜索