LUCKYNUM – spoj

Đề bài:

Thuật toán:

  • Duyệt BFS.
  • F[i,j] là phần dư của 88..866..6 (i số 8, j số 6) cho X.

Code:

#include 
#define fi first
#define se second
#define mp make_pair

using namespace std;

const int MAXN = 203;
const int MAXQ = MAXN * MAXN;
int i, j, t, X, f[MAXN][MAXN];
queue< pair > q;

int mu (int n) {
    int tmp = 1;
    for (int i = 1; i <= n; i++) tmp = (tmp * 10) % X;
    return tmp;
}

void print(int x, int y) {
    for (int i = 1; i <= x; i++) cout << 8;
    for (int i = 1; i <= y; i++) cout << 6;
    cout << endl;
}

void bfs() {
    while (!q.empty()) q.pop();
    q.push( make_pair(0,0) );
    pair x;
    while (q.size()) {
        x = q.front();
        q.pop();
        if (x.fi+x.se >= MAXN) {cout << -1 << endl; return;}
        if (f[x.fi][x.se+1] == 0) q.push(mp(x.fi,x.se+1));
        if (f[x.fi+1][x.se] == 0) q.push(mp(x.fi+1,x.se));
        f[x.fi+1][x.se] = (f[x.fi][x.se] + mu(x.fi+x.se) * 8) % X;
        f[x.fi][x.se+1] = (f[x.fi][x.se] * 10 + 6) % X;
        if (f[x.fi][x.se+1] == 0) {print(x.fi,x.se+1); return;}
        if (f[x.fi+1][x.se] == 0) {print(x.fi+1,x.se); return;}
    }
}

void process() {
    cin >> X;
    memset(f,0,sizeof(f));
    bfs();
}

int main() {
    cin >> t;
    for (int i = 1; i <= t; i++) {
        process();
    }
    return 0;
}
const   fi='';
        fo='';
        maxn=201;
type    point=record
                x,y:integer;
                end;
var     q:array[1..maxn*maxn+1] of point;
        f:array[0..maxn,0..maxn] of longint;
        t,n:integer;
        d,c:longint;
procedure xuat(x,y:integer);
var     i:integer;
begin
    for i:=1 to x do write('8');
    for i:=1 to y do write('6');
    writeln;
end;
procedure push(x,y:integer);
begin
    inc(c);
    q[c].x:= x;
    q[c].y := y;
end;
function mu(a:integer):longint;
var     i:integer;
        tam:longint;
begin
    tam:=1;
    for i:=1 to a do tam:=(tam*10) mod n;
    exit(tam);
end;
procedure xuly;
var
        x,y:integer;
begin

    d:=1;c:=1;
    q[1].x:=0;q[1].y:=0;

    while d<=c do
        begin
            x:=q[d].x; y:=q[d].y;
            inc(d);
            if (x+y>0) and (f[x,y]=0) then begin xuat(x,y); exit; end;

            if (y+1+x<=200) and (f[x,y+1]=-1) then
                begin
                    f[x,y+1]:= (f[x,y]*10 +6) mod n ;
                    push(x,y+1);
                end;

            if (x+1+y<=200) and (f[x+1,y]=-1)  then
                begin
                    f[x+1,y]:=(8*mu(x+y) mod n + f[x,y] ) mod n ;
                    push(x+1,y);
                end;

            if x+y>200 then begin writeln(-1); exit; end;
        end;
        writeln(-1);
end;
procedure init;
var     i,j:integer;
begin
    for i:=0 to 200 do
        for j:=0 to 200 do f[i,j]:=-1;

        f[0,0]:=0;
end;
procedure main;
var     i:integer;
begin
    assign(input,fi);reset(input);
    assign(output,fo);rewrite(output);

    readln(t);
    for i:=1 to t do
        begin

            readln(n);
            init;
            xuly;

        end;

    close(input);close(output);
end;
begin
    main;
end.

VO17TV – spoj

Đề bài

Thuật toán

  • (đang cập nhập)

Code

#include 
#define FORE(i, a, b) for(int i = (a); i <= (b); ++i)
#define FORD(i, a, b) for(int i = (a); i >= (b); --i)
#define FOR(i, a, b) for(int i = (a); i < (b); ++i)
#define X first
#define Y second
#define ll long long
#define mp make_pair
#define pb push_back
#define endl '\n'

const int MAXN = 1e5 + 2;
const int base1 = 1e9 + 7;
const int base2 = 1e9 + 289;
const int N = 5000;

using namespace std;
struct data
{
    int x1,x2,id;
}dd[MAXN];
int n,k;
int len[MAXN];
ll M1[MAXN],M2[MAXN],h1[51][MAXN],h2[51][MAXN];

void build1(ll h[],string s,int n)
{
    FORE(i,1,n)
    h[i] = (h[i-1]*M1[1] + s[i-1])%base1;
}

int get1(ll h[],int l,int r)
{
    return (h[r] - h[l-1]*M1[r-l+1] + 1ll*base1*base1)%base1;
}

void build2(ll h[],string s,int n)
{
    FORE(i,1,n)
    h[i] = (h[i-1]*M2[1] + s[i-1])%base2;
}

int get2(ll h[],int l,int r)
{
    return (h[r] - h[l-1]*M2[r-l+1] + 1ll*base2*base2)%base2;
}

int cmp(data a,data b)
{
    if (a.x1 != b.x1) return a.x1 < b.x1;
    if (a.x2 != b.x2) return a.x2 < b.x2;
    return a.id < b.id;
}

int check(int r)
{
    int cnt = 0;
    FORE(i,1,n)
    {
        int rr = len[i] - r + 1;
        FORE(j,1,rr)
        {
            int x1 = get1(h1[i] , j , j + r - 1);
            int x2 = get2(h2[i] , j , j + r - 1);
            dd[++cnt].x1 = x1;
            dd[cnt].x2 = x2;
            dd[cnt].id = i;
        }
    }
    sort(dd+1,dd+cnt+1,cmp);
    int dem = 0;
    FORE(i,1,cnt)
    if (dd[i].x1 != dd[i-1].x1 || dd[i].x2 != dd[i-1].x2)
    {
        dem = 1;
    }
    else
    if (dd[i].id != dd[i-1].id)
    {
        ++dem;
        if (dem == k) return 1;
    }
    return 0;
}

int main()
{
    ios_base::sync_with_stdio(0); cin.tie(0);
    #ifndef ONLINE_JUDGE
    freopen("vo17tv.inp", "r", stdin);
    freopen("vo17tv.ans", "w", stdout);
    #endif
    M1[1] = 2802; M2[1] = 2208;
    cin>>n>>k;
    int lenmi = 0;
    FORE(i,1,n)
    {
        string st;
        cin>>st;
        len[i] = st.size();
        build1(h1[i] , st , len[i]);
        build2(h2[i] , st , len[i]);
        lenmi = max(lenmi , len[i]);
    }
    FORE(i,2,lenmi) M1[i] = M1[i-1]*M1[1]%base1;
    FORE(i,2,lenmi) M2[i] = M2[i-1]*M2[1]%base2;
    int l = 1;
    int r = lenmi;
    int ans = 0;
    while(l <= r)
    {
        int mid = (l+r)>>1;
        if (check(mid))
        {
            l = mid + 1;
            ans = mid;
        }
        else
            r = mid - 1;
    }
    cout<

VO17PHD – spoj

Đề bài

Thuật toán

  • (đang cập nhập)

Code

#include 
using namespace std;
#define FORE(i,a,b) for(int i = a; i <= b; ++i)
#define FORD(i,a,b) for(int i = a; i >= b; --i)
#define FOR(i,a,b) for(int i = a; i < b; ++i)
#define pb push_back
#define endl '\n'
#define ll long long
#define X first
#define Y second

const int MAXN = 1e5 * 5;
const int base = 1e9 + 7;
const int N = 5000;
typedef pair ii;
typedef pair iii;

int n,m;
int p[MAXN];
ll d[MAXN],f[MAXN];
priority_queue h;
vector a[MAXN],c[MAXN];

void dijkstra()
{
    FORE(i,1,n) d[i] = 1e15;
    FORE(i,1,n) f[i] = 0;
    d[1] = 0;
    f[1] = p[1];
    h.push(iii(ii(0,p[1]),1));
    while(h.size())
    {
        int u = h.top().Y;
        ll du = -h.top().X.X;
        ll fu = h.top().X.Y;
        h.pop();
        if (du != d[u] || f[u] != fu) continue;
        for(int i = 0; int v = a[u][i]; ++i)
        if (d[v] > d[u] + c[u][i])
        {
            d[v] = d[u] + c[u][i];
            f[v] = f[u] + p[v];
            h.push(iii(ii(-d[v],f[v]),v));
        }
        else
        if (d[v] == d[u] + c[u][i] && f[v] < f[u] + p[v])
        {
            f[v] = f[u] + p[v];
            h.push(iii(ii(-d[v],f[v]),v));
        }
    }
}

int main()
{
    ios_base::sync_with_stdio(0); cin.tie(0);
    //freopen("vo17phd.inp" , "r" , stdin);
    //("vo17phd.out" , "w" , stdout);
    cin>>n;
    FORE(i,1,n) cin>>p[i];
    cin>>m;
    FORE(i,1,m)
    {
        int u,v,w;
        cin>>u>>v>>w;
        a[u].pb(v); c[u].pb(w);
        a[v].pb(u); c[v].pb(w);
    }
    FORE(i,1,n) a[i].pb(0);
    dijkstra();
    if (d[n] == 1e15) cout<<"impossible"<

VO17LAN – spoj

Đề bài

Thuật toán

  • (đang cập nhập)

Code

#include 
using namespace std;
#define FORE(i,a,b) for(int i = a; i <= b; ++i)
#define FORD(i,a,b) for(int i = a; i >= b; --i)
#define FOR(i,a,b) for(int i = a; i < b; ++i)
#define pb push_back
#define endl '\n'
#define ll long long
#define X first
#define Y second

const int MAXN = 1e5 * 5;
const int base = 1e9 + 7;
const int N = 55000;

int t,n;
int ans;
int a[N];

int gcd(int a,int b)
{
    if (b == 0) return a;
    else return gcd(b,a%b);
}

void upd(int d)
{
    if (d <= ans) return;
    int gcd1 = a[1];
    int gcd2 = 0;
    FORE(i,2,n)
    {
        if (a[i]%d == 0) gcd1 = gcd(gcd1 , a[i]);
        else
        {
            if (gcd2 == 0) gcd2 = a[i];
            else gcd2 = gcd(gcd2 , a[i]);
        }
        if (gcd2 && min(gcd1 , gcd2) <= ans) return;
    }
    if (gcd2 == 0) gcd2 = gcd1;
    ans = max(ans , min(gcd1 , gcd2));
}

int main()
{
    ios_base::sync_with_stdio(0); cin.tie(0);
    //freopen("vo17lan.inp" , "r" , stdin);
    //freopen("vo17lan.out" , "w" , stdout);
    cin>>t;
    while(t--)
    {
        cin>>n;
        FORE(i,1,n) cin>>a[i];
        sort(a+1,a+n+1);
        ans = 1;
        int xx = sqrt(a[1]);
        FORD(d,xx,2)
        if (a[1]%d == 0)
        {
            upd(d);
            upd(a[1]/d);
        }
        upd(a[1]);
        cout<

NKSGAME – spoj

Đề bài:

Thuật toán:

Bài yêu cầu với mỗi số [latex]b[i][/latex] tìm [latex]c[j][/latex] sao cho [latex]|b[i]+c[j]|[/latex] nhỏ nhất. Suy ra chọn sao cho [latex]b[i]+c[j][/latex] có giá trị gần [latex]0[/latex] nhất

Thuật toán sẽ là:

  1. Sắp xếp lại mảng [latex]c[][/latex].
  2. Với mỗi [latex]b[i][/latex] tìm kiếm nhị phân [latex]c[j][/latex] thỏa mãn [latex]b[i]+c[j][/latex] có giá trị gần [latex]0[/latex] nhất.

Nếu chưa hiểu rõ bạn có thể xem code bên dưới.

Code:

#include 

using namespace std;

const int maxn = 100009;
const int oo = 2000000009;
int i, j, n, ans, tmp, b[maxn], a[maxn];

bool cmp (int x, int y) {
     return(x < y);
}

int main() {
    cin >> n;
    for (i = 1; i <= n; i++) cin >> a[i];
    for (i = 1; i <= n; i++) cin >> b[i];
    sort (b+1, b+n+1, cmp);
    ans = oo;
    for (i = 1; i <= n; i++) {
        tmp = lower_bound(b+1,b+n+1,0-a[i]) - b;
        if (tmp > n) tmp = n;
        ans = min(ans, abs(a[i] + b[tmp]));
        if (tmp == 1) continue;
        ans = min(ans, abs(a[i] + b[tmp-1]));
    }
    cout << ans;
    return 0;
}

CASTLE – spoj

Đề bài:

Thuật toán:

  • (đang cập nhập thuật toán)

Code:

uses math;
const
    tfi='';//castle.inp';
    tfo='';//castle.out';
 
var
    fi,fo:text;
    n,top1,top2,top3,dem:longint;
    tg,kq1,kq2,kq11,kq22:int64;
    p,q,a,b:array[0..5001] of longint;
    st:array[0..5001] of int64;
procedure nhap;
    var i,j:longint;
    begin
        read(fi,n);
        for i:=1 to n do read(fi,a[i],b[i]);
        kq2:=high(int64);
    end;
 
procedure swap(var x,y:longint);
    var tg:longint;
    begin
        tg:=x;
        x:=y;
        y:=tg;
    end;
 
procedure sort(l,r:longint);
    var i,j,k,k1,k2:longint;
    begin
        i:=l;
        j:=r;
        k:=l+random(r-l+1);
        k1:=a[k];
        k2:=b[k];
        repeat
            while (a[i]k1) or ((a[j]=k1) and (b[j]>k2)) do dec(j);
            if i<=j then
                begin
                    swap(a[i],a[j]);
                    swap(b[i],b[j]);
                    inc(I);
                    dec(j);
                end;
        until i>j;
        if i=2 then
        begin
        tg:=int64(st[top3]-st[1])*(v-u);
        if tg=kq1 then inc(kq11);
        if tg>kq1 then
            begin
                kq1:=tg;
                kq11:=1;
            end;
        end;
        for i:=2 to top3 do
            begin
                tg:=int64(st[i]-st[i-1])*(v-u);
                if tg=kq2 then inc(kq22);
                if tga[i] then break
                    else
                        begin
                            inc(top1);
                            q[top1]:=b[j];
                        end;
                if j>n then break;
                k:=j;
                while k<=n do
                    begin
                        top2:=0;
                        for k1:=k to n+1 do
                            if a[k1]<>a[k] then break
                            else
                                begin
                                    inc(top2);
                                    p[top2]:=b[k1];
                                end;
                        lam(a[i],a[k]);
                        k:=k1;
                    end;
                i:=j;
            end;
        writeln(fo,dem);
        if dem>0 then
            begin
                writeln(fo,kq1,' ',kq11);
                writeln(fo,kq2,' ',kq22);
            end;
    end;
 
begin
    assign(fi,tfi);
    assign(fo,tfo);
    reset(fi);
    rewrite(fo);
    nhap;
    xuli;
    close(fo);
end.

C11SUM – spoj

Đề bài:

Thuật toán:

  • Các bạn đọc code xem thuật toán dễ thế nào nhé 🙂

Code:

{$H+}
Uses math;
Const
	inp = '';
	out = '';
	maxn = 1000001;
	oo = 1000000007;

Var
	a,b : array [0..maxn] of int64;
	s : string;
	n,i,x : longint;
	res,hold : int64;

begin
	assign(input,inp); reset(input);
	assign(output,out); rewrite(output);
	readln(s);
	n := length(s);
	hold := 0;
	for i := 1 to n do
	  begin
	  	x := ord(s[i])-ord('0');
	  	hold := (hold*10+i*x) mod oo;
	  	res := (res +hold) mod oo;
	  end;
	writeln(res);
end.

C11BC2 – spoj

Đề bài:

Thuật toán:

  • Bài này chỉ cần LCA thôi. Dễ mà bạn tự nghĩ sẽ ra…

Code:

const
  fi='';
  fo='';
  maxn=trunc(1e5);
  maxm=trunc(1e5);
  maxp=20;
var
  link,head,ke,ts : array[-maxm..maxm] of longint;
  i,j,n,m,x,y,q,qq : longint;
  depth,cha,cau : array[1..maxn] of longint;
  p : array[1..maxn,0..maxp] of longint;
  ok : array[1..maxn,0..maxp] of boolean;
  cx : array[1..maxn] of boolean;
procedure add(i,u,v,w : longint);
  begin
    link[i] := head[u];
    head[u] := i;
    ke[i] := v;
    ts[i] := w;
  end;
procedure enter;
  var u,v ,w :longint;
  begin
    assign(input,fi);reset(input);
    readln(n,q);
    for i:=2 to n do
      begin
        read(v,w);
        add(i,i,v,w);
        add(-i,v,i,w);
      end;
  end;
procedure dfs(u : longint);
  var i,j,v : longint;
  begin
    cx[u] := false;
    i:=head[u];
    while i<>0 do
      begin
        v:=ke[i];
        if cx[v] then
        begin
          cau[v] := i;
          cha[v] := u;
          depth[v] := depth[u]+1;
          dfs(v);
        end;
        i:=link[i];
      end;
  end;
procedure init;
  var i,u : longint;
  begin
    fillchar(cx,sizeof(cx),true);
    cha[1] := 1;
    depth[1] := 1;
    dfs(1);
    for i:=1 to n do
      begin
        p[i,0] := cha[i];
        if cau[i]<>0 then
          if ts[cau[i]]=2 then
            ok[i,0] := true;
      end;
      for i:=1 to maxp do
      for u:=1 to n do
        begin
          p[u,i] := p[p[u,i-1],i-1];
          ok[u,i] := ok[u,i] or ok[u,i-1] or ok[p[u,i-1],i-1];
        end;
  end;
function lca ( u,v : longint) : boolean;
  var res : boolean;
  begin
    res := false;
    for i:=maxp downto 0 do
      if depth[p[u,i]]>=depth[v] then
        begin
          res := res or ok[u,i];
          u := p[u,i];
        end;
    for i:=maxp downto 0 do
      if depth[p[v,i]]>=depth[u] then
        begin
          res := res or ok[v,i];
          v := p[v,i];
        end;
    if u=v then
      begin
        //writeln(u);
        exit(res);
      end;
        for i:=maxp downto 0 do
          if p[u,i]<>p[v,i] then
          begin
            res := res or ok[u,i];
            res := res or ok[v,i];
            u := p[u,i];
            v := p[v,i];
          end;
    res := res or (ok[u,0]) or (ok[v,0]);
    //writeln(cha[u]);
    exit(res);
end;
procedure process;
  var x,y : longint;
  begin
    assign(output,fo);rewrite(output);
    for qq := 1 to q do
      begin
        read(x,y);
        if lca(x,y) then writeln('YES') else writeln('NO');
      end;
    close(output);
  end;
begin
  enter;
  init;
  process;
end.

DTDOI – spoj

Đề bài:

Thuật toán:

  • Thông thường thì ta sẽ có cách giải QHĐ với đpt O(S*n), nhưng vì S lên đến 1e9 nên ta có cách làm như sau:
    -Giảm S bằng tờ có giá trị lớn nhất cho đến khi S đủ nhỏ để QHĐ (giảm đến mức nào thì các bạn nên tự thử, trong code mình giảm xuống 100000)
    -QHĐ

Code:

#include
using namespace std;
int n,s;
int a[101];
int d[100001];
int main()
{
	cin>>n>>s;
	for (int i=1; i <= n; i++)
		cin>>a[i];
	int mx=0;
        for (int i=1; i <= n; i++)
                mx=max(mx,a[i]);
	int res=0;
	while (s >= 100001)
		{
			res++;
			s-=mx;
		}
	d[0]=0;
	for (int i=1; i <= s; i++)
		{
                        d[i]=10000000;
                        for (int j=1; j <= n; j++)
			        if (i >= a[j])
				         d[i]=min(d[i],d[i-a[j]]+1);
                }
	cout<

C11TRCNT – spoj

Đề bài:

Thuật toán:

  • Bài toán đưa về: kiểm tra 3 điểm có thẳng hàng hay không

Code:

const   fi='';
        fo='';
type    dinh=record
                x,y:longint;
                end;
var     i,j,k:integer;
        d,max,min:int64;
        kq,n:byte;
        p:array[1..200] of dinh;
        dem:array[1..200] of int64;
        f:text;
procedure nhap;
begin
    assign(f,fi);
    reset(f);
    readln(f,n);
    for i:=1 to n do readln(f,p[i].x,p[i].y);
    close(f);
end;
function kt(x1,y1,x2,y2,x3,y3:longint):boolean;
begin
        if x1*y3-x1*y2+x2*y1-x2*y3+x3*y2-x3*y1=0
        then exit(false) else exit(true);
end;
procedure xuly;
begin
    d:=0; min:=1000000000000000;
    for i:=1 to n do
    begin
        for j:=1 to n do
        if i<>j then
                for k:=1 to n do
                if (i<>k) and (j<>k) then
                                if kt(p[i].x,p[i].y,p[j].x,p[j].y,p[k].x,p[k].y)  then
                                begin
                                        inc(dem[i]);
                                        if (ij) then inc(d);
                                end;
        if dem[i]