STABLE – spoj

Đề bài:

Thuật toán:

  • BFS từ đỉnh S
  • Gọi bac[i] là đồ dài đường đi ngắn nhất từ s đến i
    • bac[i] = bac[j] + 1
    • với i kề j và j duyệt BFS trước i
  • ok[i] = 1 nếu i ổn định, ok[i] = 0 nếu i không ổn định.
  • Hãy tham khảo code để biết cách kiểm tra xem i có ổn định không

Code:

#include 
using namespace std;
#define FOR(i,a,b) for (int i=(a),_b=(b);i<=_b;i=i+1)
#define FORD(i,b,a) for (int i=(b),_a=(a);i>=_a;i=i-1)
#define REP(i,n) for (int i=0,_n=(n);i<_n;i=i+1)
#define FORE(i,v) for (__typeof((v).begin()) i=(v).begin();i!=(v).end();i++)
#define ALL(v) (v).begin(),(v).end()
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
#define double db
typedef long long ll;
typedef pair PII;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
const int MAXN = 1E4+3;
const int oo = 1e9+3;

int n, m, s, u, v, res, bac[MAXN],adj[MAXN][MAXN];
bool ok[MAXN];
queue q;
vector a[MAXN];

int main() {
    	#ifndef ONLINE_JUDGE
    	freopen("test.inp", "r", stdin);
    	freopen("test.out", "w", stdout);
    	#endif
    cin >> n >> m >> s;
    FOR(i,1,m) {
        cin >> u >> v;
        if (!adj[u][v])
            a[u].push_back(v);
        adj[u][v] = 1;
    }
    q.push(s); bac[s] = 1;
    while (!q.empty()) {
        u = q.front();
        q.pop();
        for(int i=0; i
const
  fi='stable.inp';
  fo='stable.out';
  maxn=10000;
  maxm=50000;
var
  link,head,ke : array[1..maxm] of longint;
  i,j,n,m,st,ans,s,dau,cuoi,u,v : longint;
  q,bac : array[1..maxn] of longint;
  ok : array[1..maxn] of boolean;
  a : array[1..maxn,1..maxn] of boolean;
procedure push(x : longint);
  begin
    inc(cuoi);
    q[cuoi] := x;
  end;
procedure add(i,u,v : longint);
  begin
    link[i] := head[u];
    head[u] := i;
    ke[i] := v;
  end;
begin
//  assign(input,fi);reset(input);
//  assign(output,fo);rewrite(output);
  read(n,m,s);
  for i := 1 to m do
    begin
      read(u,v);
      if a[u,v] = false then
      add(i,u,v);
      a[u,v] := true;
    end;
  dau := 1; cuoi := 0;
  push(s);
  bac[s] := 1;
  while (dau <= cuoi) do
    begin
      u := q[dau];
      inc(dau);
      i := head[u];
      while i <> 0 do
        begin
          v := ke[i];
          if bac[v] = 0 then
            begin
              if ok[u] then ok[v] := true;
              bac[v] := bac[u] + 1;
              push(v);
            end
            else
          if bac[v] = bac[u] + 1 then
            begin
              ok[v] := true;
            end;
          i := link[i];
        end;
    end;
  for i := 1 to n do
    if ok[i] then inc(ans);
  writeln(ans);
//  close(input);close(output);
end.

APIO10A – spoj

Đề bài: http://www.spoj.com/problems/APIO10A/


Cho 1 dãy N số nguyên. Một hàm số bậc 2 : f(x) = a * x ^ 2 + b * x + c. Phân dãy trên thành các đoạn liên tiếp sao cho tổng các hàm f trên các dãy là lớn nhất (giá trị f của 1 dãy là f(x) với x là tổng của dãy đó).

Input format :

  • Dòng đầu là số test case T
  • Mỗi test case gồm 3 dòng :
    • Dòng đầu là số nguyên dương N – số phần tử của dãy.
    • Dòng 2 là 3 số nguyên a, b, c.
    • Dòng còn lại gồm n số x1, x2, …, xn là n phần tử của dãy.

Output format :

  • Mỗi test case gồm 1 dòng, là kết quả của bài toán.

Giới hạn :

T<=3

n ≤ 1, 000, 000,

−5 ≤ a ≤ −1

b <= 10,000,000

c <= 10,000,000

1 ≤ xi ≤ 100.

Thuật toán:


Gọi f(x) = a * x ^ 2 + b * x + c

Thuật O(n^2):

Gọi dp(i) là chi phí lớn nhất khi phân hoạch đoạn từ 1 -> i.

sum(i) là tổng các phần tử từ 1 -> i.

dp(i) = max(dp(j) + f(sum(i) – sum(j)) (1 <= i <= n; 0 <= j < i)

 

Thuật O(n): dùng Convex Hull Trick

dp(i) = max(dp(j) + f(sum(i) – sum(j)) (1 <= i <= n; 0 <= j < i)

⇔ dp(i) = dp(j) + a * (sum(i) – sum(j))^ 2 + b * (sum(i) – sum(j)) + c

⇔ dp(i) = (a * sum(i) ^ 2 + b * sum(i) + c) + (-2 * a * sum(i) * sum(j)) + a * sum(j) ^ 2 – b * sum(j) ^ 2

Đặt A = -2 * a * sum(j), X = sum(i), B = a * sum(j) ^ 2 – b * sum(j) ^ 2

⇔ ta được đường thẳng y = A * X + B.

Vì mảng sum tăng dần -> ta có thể dùng two-pointer để giảm đpt xuống O(n)

Code:


#include 
using namespace std;

const int N = 1e6 + 10;

class ConvexHull {
private:
    int head, tail;
    long long A[N], B[N];
public:
    void init() { head = tail = 0; }
    bool bad(int l1, int l2, int l3) {
        return (long double) (B[l3] - B[l1]) / (A[l1] - A[l3]) < (long double) (B[l2] - B[l1]) / (A[l1] - A[l2]);
    }
    void add(long long a, long long b) {
        A[tail] = a; B[tail++] = b;
        while (tail > 2 && bad(tail - 3, tail - 2, tail - 1)) {
            A[tail - 2] = A[tail - 1];
            B[tail - 2] = B[tail - 1];
            tail--;
        }
    }
    long long query(long long x) {
        if (head >= tail) head = tail - 1;
        while (head < tail - 1
               && A[head + 1] * x + B[head + 1] >= A[head] * x + B[head]) head++;
        return A[head] * x + B[head];
    }
} hull;

int n, a, b, c;
long long sum[N];

long long f(long long x) { return a * x * x + b * x + c; }

void load() {
    scanf("%d%d%d%d", &n, &a, &b, &c);
    for (int i = 1; i <= n; ++i) {
        scanf("%lld", sum + i);
        sum[i] += sum[i - 1];
    }
}

void process() {
    hull.init();
    long long cost = f(sum[1]);
    hull.add(-2 * a * sum[1], cost + a * sum[1] * sum[1] - b * sum[1]);

    for (int i = 2; i <= n; ++i) {
        cost = f(sum[i]) + max(0ll, hull.query(sum[i]));
        hull.add(-2 * a * sum[i], cost + a * sum[i] * sum[i] - b * sum[i]);
    }
    printf("%lld\n", cost);
}

int main() {
  //  freopen("input.in", "r", stdin);
 //   freopen("output.out", "w", stdout);

    int test; scanf("%d", &test);
    while (test--) {
        load();
        process();
    }

    return 0;
}

NKPATH – spoj

[mathjax]

Đề bài:


Thuật toán:


Với mỗi ô (i,j) với  $i=1..m; j=1..n-1;$ kiểm tra xem ô (ii,jj) với $ii=1..i-1; jj=1..j;$ có đi được đến ô (i,j) không

  • Nếu có
    l[i,j]:=(l[i,j]+l[ii,jj]) mod base;
    

Kết quả: $\sum_{i=1}^{m}L[i][n]$

Code:


const   fi='';
        fo='';
        maxn=100;
        base=1000000000;
type    arra=array[1..maxn,1..maxn] of integer;
        arrl=array[1..maxn,1..maxn] of longint;
var     a:arra;
        i,j,m,n:byte;
        l:arrl;
        f:text;
        res:int64;
procedure nhap;
begin
    assign(f,fi);
    reset(f);
    readln(f,m,n);
    for i:=1 to m do
        for j:=1 to n do read(f,a[i,j]);
    close(f);
end;
procedure init;
begin
    for i:=1 to m do l[i,1]:=1;

    res:=0;
end;
function kt(x,y:longint):boolean;
var     tmp:longint;
begin
        while y>0 do
        begin
            x:=x mod y;
            tmp:=x;
            x:=y;
            y:=tmp;
        end;
        if x=1 then exit(false) else exit(true);
end;
procedure xuly;
var     ii,jj:byte;
begin
    for i:=1 to m do
        for j:=1 to n-1 do
        begin
            for ii:=i-1 downto 1 do
                for jj:=j downto 1 do
                        if kt(a[i,j],a[ii,jj]) then l[i,j]:=(l[i,j]+l[ii,jj]) mod base;
            for jj:=j-1 downto 1 do
                if kt(a[i,j],a[i,jj]) then l[i,j]:=(l[i,j]+l[i,jj]) mod base;
        end;

    for i:=1 to m do
        for ii:=i downto 1 do
                for jj:=n-1 downto 1 do
                if kt(a[i,n],a[ii,jj]) then res:=(res+l[ii,jj]) mod base;
end;
procedure xuat;
begin
    assign(f,fo);
    rewrite(f);
    writeln(f,res);
    close(f);
end;
begin
    nhap;
    init;
    xuly;
    xuat;
end.

C11BC1 – spoj

Đề bài:


Thuật toán:


  • (đang cập nhập)

Code:


uses math;
const
  fi='';
  fo='';
  maxn=trunc(1e5);
  maxk=50;
  base=790972;
var
  f : array[0..maxn,0..maxk] of int64;
  i,j,n,k,m : longint;
  kq : int64;
  a,b : array[1..maxn] of longint;
procedure enter;
begin
  assign(input,fi);reset(input);
  readln(n,k);
  for i:=1 to n do read(a[i],b[i]);
  close(input);
end;
procedure swap(var x,y: longint);
var tg : longint;
begin
  tg:=x;x:=y;y:=tg;
end;
procedure qs(l,r : longint);
  var i,j,x : longint;
  begin
    i:=l;j:=r;
    x:=b[(l+r) div 2];
    repeat
      while x>b[i] do inc(i);
      while xj;
    if il then qs(l,j);
  end;
function muk(x : longint) : int64;
  var i : longint;
  begin
    muk := 1;
    for i:=1 to k do muk:=muk*x;
  end;
function cnk(n,k : longint) : int64;
  begin
    cnk := 1;
    for i:=n-k+1 to n do cnk := cnk*i;
    for i:=1 to k do cnk := cnk div i;
  end;
function tinh : int64;
begin
  fillchar(f,sizeof(f),0);
  for i:=0 to m do f[i,0] := 1;
  for i:=1 to m do
    for j:=1 to min(k,i) do
      f[i,j] := (f[i-1,j] + f[i-1,j-1]*a[i]) mod base;
  exit(f[m,k]);
end;
procedure process;
var i,j,dem : longint;
    dau,cuoi : longint;
begin
  qs(1,n);
  m := n;
  kq := tinh;
  dau := 1;
  while (dau<=n) do
  begin
    cuoi := dau+1;
    m := 1; a[1] := a[dau];
    while (cuoi<=n) and (b[cuoi]=b[dau]) do
      begin
        m := m+1;
        a[m] := a[cuoi];
        inc(cuoi);
      end;
    if cuoi-dau>=k then
      kq := (kq - tinh + base + base) mod base;
    dau := cuoi;
  end;
end;
procedure print;
begin
  assign(output,fo);rewrite(output);
  writeln(kq);
  close(output);
end;
begin
  enter;
  process;
  print;
end.

ACMNB – spoj

Đề bài:

Thuật toán:

Thuật toán có thể suy ra từ cách làm thực tế. Nếu Tí làm tất cả 2n bài sẽ mất tổng thời gian là

12-yeulaptrinh.pwTuy nhiên Tí phải nhường lại n bài cho Tèo. Mỗi khi Tí nhường bài i cho Tèo, thời gian S sẽ giảm đi một lượng ci = ai – bi. Ta cần chọn n bài để Tí nhường cho Tèo sao cho thời gian S giảm đi nhiều nhất, tức là phải chọn n chỉ số i có c lớn nhất.

Code:

CONST   FI='';
        FO='';
        maxn=trunc(1e5)*8;
type    arr1    =array[1..maxn] of longint;
var     n,i,j   :longint;
        a,b,c   :arr1;
        ans     :longint;
procedure enter;
begin
        assign(input,fi);reset(input);
        read(n);
        for i:=1 to 2*n do read(a[i],b[i]);
        close(input);
end;
procedure swap(var x,y:longint);
var     tg      :longint;
begin
        tg:=x;x:=y;y:=tg;
end;
procedure qs(l,r:longint; var a,b,c:arr1);
var     i,j,x,y     :longint;
begin
        i:=l;j:=r;
        x:=a[(l+r) div 2];
        y:=b[(l+r) div 2];
        repeat
                while (x>a[i])  do inc(i);
                while (xj;
        if il then qs(l,j,a,b,c);
end;
procedure process;
begin
        for i:=1 to 2*n do c[i]:=a[i]-b[i];
        qs(1,2*n,c,a,b);
        for i:= 1 to n do
                ans :=  ans+a[i];
        for i:=n+1 to 2*n do
                ans := ans+b[i];
end;
procedure print;
begin
        assign(output,fo);rewrite(output);
        writeln(ans);
        close(output);
end;
begin
        enter;
        process;
        print;
end.

Tạo form trong HTML

FORM được sử dụng để chuyển dữ liệu liệu từ người dùng nhập vào đến web server.
Form bao gồm các thành phần nhập liệu (input elements) như: Text box, hộp kiểm, nút tùy chọn, Submit…
Bài viết này mình sẽ hướng dẫn các bạn một số các thành phần của Form hay được sử dụng nhất. Mình sẽ cố gắng giải thích để mọi người có thể hiểu.
Trong tài liệu HTML form được định nghĩa bằng cặp thẻ <form></form>
Các thẻ nằm giữa cặp thẻ <form></form> được gọi là các thành phần của Form

Các thành phần Form

Thành phần được sử dụng nhiều nhất trong form là thẻ <input />. Ta sử dụng <input /> để định nghĩa các thành phần của form như: Trường nhập liệu Text, các hộp kiểm, các nút tùy chọn, trường password, thành phần submit, các button, File upload.

1. Trường text
User name:

Code:


2. Trường password
Pass:

Code:


3. Checkbox (Hộp kiểm)

Cho phép chọn nhiều thành phần từ danh sách đưa ra

Send my to email
Send my to phone

 Send my to email
Send my to phone

4. Radio button

Khác với checkbox, Radio chỉ phép phép chọn một thành phần từ danh sách đưa ra, các phần tử trong danh sách phải có cùng tên, như ví dụ sau ta
sẽ tạo ra hai thành phần Radio button có cùng tên là name=”gender”

Male
Female

 Male
 Female

5. File upload


6. Button

Tạo ra một nút bấm trên form


7. Submit Button

Tạo nút submit trên form. Khi nút Submit được nhấn, dữ liệu trên form sẽ đuợc xử lý và gửi đi


8. Reset Button

Tạo nút Reset trên form. Khi nhấn nút Reset dữ liệu nhập vào form sẽ được reset về giá trị ban đầu của form


Ta nhận thấy sự khác biệt giữa các thành phần input là thuộc tính type. Thuộc tính type sẽ quy định thành phần input này là Text, password, checkbox, hay button …

9. Dropdown list

Student
Bussiness
Manager
Other…


KẾT LUẬN

– Mỗi thành phần form đều được gán một tên (name=”ten_thanh_phan”): đây chính là tên biến được sử dụng trong các ngôn ngữ lập trình web như php hay asp.net…, Riêng thành phần Radio trong cùng một nhóm sẽ được đặt cùng tên.

– Thuộc tính value=”Giá trị”: đây là giá trị (dữ liệu) ban đầu của thành phần form, các thành phần không có thuộc tính value giá có giá trị ban đầu là rỗng (null).

– Các Phương thức hoạt động của form bạn có thể xem ở các bài tiếp thep.

P171SUMB – ptit

Đề bài:

Thuật toán:

  • Gọi [latex]cnt[i][/latex] là số các số chia mod k = i trong tập [latex]S[/latex].
  • Theo đề bài ta có: [latex]KQ = KQ + max(cnt[i], cnt[k-i])[/latex] với [latex]i=1..k/2[/latex].
    • Chú ý nếu n mod 2 = 0 thì ta không cộng [latex]cnt[n/2][/latex] vào KQ mà chỉ cộng 1 thôi.

Code:

#include 
using namespace std;
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector VI;
typedef long long ll;
typedef pair PII;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
int n, k, i, j, a[200004], cnt[500], ans;
int main() {
    cin >> n >> k;
    for (int i=1; i<=n; i++) cin >> a[i];
    for (int i=1; i<=n; i++) {
        a[i] = a[i] % k;
        ++cnt[a[i]];
    }
    for (int i=1; i<=k/2; i++) {
        ans = ans + max(cnt[i], cnt[k-i]);
    }
    if (k%2 == 0) {
        ans -= cnt[k/2];
        if (cnt[k/2]>0) ans++;
    }
    if (cnt[0] > 0) ans++;
    cout << ans;
	return 0;
}

P171SUMD – ptit

Đề bài:

Thuật toán:

  • Ưu tiên di chuyển hàng trước nếu m < n và ngược lại.
  • Sử dụng thuật toán tham lam trừ từng hàng và từng từng cột.

Code:

#include 
using namespace std;
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector VI;
typedef long long ll;
typedef pair PII;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
const int MAXN = 200;
const int oo = 1000;
int m, n, i, j, g[MAXN][MAXN], kt, mi, tam, dadoi;
vector H, C;

void xulyhang() {
    for (int i=1; i<=m; i++) {
        mi = oo;
        for (int j=1; j<=n; j++) mi = min(mi, g[i][j]);
        for (int j=1; j<=mi; j++) H.push_back(i);
        for (int j=1; j<=n; j++) g[i][j]-=mi;
    }
}

void xulycot() {
    for (int j=1; j<=n; j++) {
        mi = oo;
        for (int i=1; i<=m; i++) mi = min(mi, g[i][j]);
        for (int i=1; i<=mi; i++) C.push_back(j);
        for (int i=1; i<=m; i++) g[i][j]-=mi;
    }
}

int main() {
    cin >> m >> n;
    for (int i=1; i<=m; i++)
        for (int j=1; j<=n; j++) cin >> g[i][j];
    kt = 1;
    if (m < n) {
        xulyhang();
        xulycot();
    }
    else {
        xulycot();
        xulyhang();
    }
    for (int i=1; i<=m; i++)
        for (int j=1; j<=n; j++)
        if (g[i][j]!=0) kt = 0;
    if (kt==0) cout << -1;
    else {
            cout << C.size()+H.size() << endl;
            for (int i=0; i

C11STR2 – spoj

Đề bài:

Thuật toán:

  • Nhận thấy nếu [latex]x[/latex] ký tự cuối của xâu [latex]a[/latex] trùng với [latex]x[/latex] ký tự cuối của xâu [latex]b[/latex] thì có thể ghép. Để kiểm tra hai xâu con có trùng nhau không với ĐPT O(n) thì ta sử dụng Hash.
  • Ta cần tìm [latex]x[/latex] lớn nhất.
  • Ta sẽ duyệt [latex]x[/latex] từ max(length(a),length(b)) về 0. Nếu đã tìm thấy [latex]x[/latex] thỏa mãn thì break.

Code:

{$H+}
uses math;
const
  fi='';
  fo='';
  base=trunc(1e9);
  pp=307;
  maxn=trunc(1e5);
var
  a,b,c : string;
  i,j,n,m : longint;
  ha,hb : array[0..maxn] of int64;
  pow : array[0..maxn] of int64;
procedure enter;
begin
  assign(input,fi);reset(input);
  readln(a);
  readln(b);
  close(input);
end;
procedure swap( var m,n : longint; var a,b : string);
var tg1 : longint;
    tg2 : string;
begin
  tg1 := m ; m := n ; n:= tg1;
  tg2 := a; a :=b ; b:= tg2;
end;
function getha(l,r : longint) : int64;
  begin
    getha := (ha[r]-ha[l-1]*pow[r-l+1] + base*base)  mod base;
  end;
function gethb(l,r : longint) : int64;
  begin
    gethb := (hb[r]-hb[l-1]*pow[r-l+1] + base*base) mod base;
  end;
procedure process;
begin
  m := length(a); n := length(b);
  c := a + b;
  //if m

MINK – spoj

Đề bài:

Thuật toán:

  • Bài này chỉ thuần sử dụng thuật toán Kỹ thuật sử dụng Deque tìm Max/Min trên một đoạn tịnh tiến

Code:

const   fi='';
        fo='';
        maxn=17000;
var     a:array[1..maxn] of longint;
        hold:array[1..maxn] of integer;
        i,j,n,k,t:integer;
        top,below:integer;
procedure push(i:integer);
begin
    while (top<>below-1) and (a[i]top+1) and (hold[below]<=i) do inc(below);
end;
procedure print;
begin
    write(a[hold[below]],' ');
end;
procedure solve;
var     i:integer;
begin
    top:=0; below:=1;
    for i:=1 to k do push(i); print;
    for i:=k+1 to n do
        begin
            pop(i-k);
            push(i);
            print;
        end;
    writeln;
end;
procedure main;
var     i,j:integer;
begin
    assign(input,fi);reset(input);
    assign(output,fo);rewrite(output);

    readln(t);
    for i:=1 to t do
        begin
            read(n,k);
            for j:=1 to n do read(a[j]);
            solve;
        end;

    close(input);close(output);
end;
begin
    main;
end.
#include 
using namespace std;
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector VI;
typedef long long ll;
typedef pair PII;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
deque q;
int i, n, k, a[20000], t, tt;
int main() {
	cin >> t;
	for (int tt=1; tt<=t; tt++) {
        cin >> n >> k;
        for (int i=1; i<=n; i++) cin >> a[i];
        while (!q.empty()) q.pop_back();
        for (int i=1; i<=n; i++) {
            while ((!q.empty())&&(q.front() < i-k+1)) q.pop_front();
            while ((!q.empty())&&(a[q.back()]>a[i])) q.pop_back();
            q.push_back(i);
            if (i>=k) cout << a[q.front()] << " ";
        }
        cout << endl;
	}
	return 0;
}