listgame – kattis

[mathjax]
[su_accordion][su_accordion]
[su_spoiler title=”Đề bài” open=”yes”]
Có hai người chơi trò chơi với nhau, luật như sau:

  • Người thứ nhất chọn một số nguyên dương X
  • Người thứ hai tìm các số $Y_1, Y_2, .. Y_k$ sao cho $(Y_1 + 1)(Y_2 + 1)…(Y_k + 1) = X$. Khi đó người chới thứ hai được k điểm

Cho X tìm số điểm tối đa mà người chơi thứ hai có thể đạt

Input:

Số nguyên dương $X$ thỏa mãn $10^3 <= X <= 10^9$

Output:

Duy nhất số K là số điểm tối đa có thể đạt

Sample Input 1 65536
Sample Output 1 16

 

Sample Input 2 127381
Sample Output 2 3

[/su_spoiler]
[su_spoiler title=”Thuật toán”]

  • Nếu n là số nguyên tố => Kết quả: 1
  • Nếu không thì ta phần tích X thành tích các số nguyên tố => Kết quả: là số các số hạng phân tích được
  • Ví dụ: 12 = 2 * 2 * 3 => Kết quả: 3

[/su_spoiler]
[su_spoiler title=”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 = 1E6+3;
const int oo = 1e6+3;

bool prime[MAXN];
int i, j, x, cnt, k, sl[MAXN], nt[MAXN];

void tim_snt() {
    prime[1] = 1;
    int n = trunc(sqrt(oo));
    for(i=2; i<=n; i++) {
        if (!prime[i]) {
            j = i*i;
            while (j <= oo) {
                prime[j] = 1;
                j += i;
            }
        }
    }
    cnt = 0;
    for(i=2; i<=oo; i++) if (!prime[i]) {
        cnt++;
        nt[cnt] = i;
    }
}

void phan_tich() {
    int i = 1;
    while (x > 1) {
        while ((x > 1)&&(x % nt[i] == 0))
        {
            k++;
            x /= nt[i];
        }
        i++;
        if (i > cnt) break;
    }
    if (x > 1) k++;
}

bool ktnt(int x) {
    int n = trunc(sqrt(x));
    FOR(i,2,n) {
        if (x % i == 0) return 0;
    }
    return 1;
}

int main() {
    cin >> x;
    if (ktnt(x)) {
        cout << 1;
        return 0;
    }
    tim_snt();
    phan_tich();
    cout << k;
    return 0;
}

[/su_spoiler]
[/su_accordion]

NKNUMFRE – spoj

Đề bài:

Thuật toán:

  • Vét cạn.

Code:

const
  fi='';
  fo='';
var
  a,b,i,j,dem,num : longint;
procedure swap(var x,y : char);
  var tg :char;
  begin
    tg:=x;x:=y;y:=tg;
  end;
function gcd(a,b : longint) : longint;
  var r : longint;
  begin
    while b>0 do
      begin
        r := a mod b;
        a:=b;
        b:=r;
      end;
    exit(a);
  end;
function dao(x : longint) : longint;
  var s : string;
      y : longint;
  begin
    str(x,s);
    i:=1;j:=length(s);
    while i

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

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]

LEM3 – spoj

Đề bài:

Thuật toán:

  • Đây là bài cơ bản của thuật toán quy hoạch động trạng thái.
  • Nếu giải bài này bằng duyệt sẽ không ăn được hết test.
  • Gọi F[i,state] là độ dài hành trình ngắn nhất khi đến được i và trạng thái thăm/chưa thăm các thành phố là state
    • state có dạng dãy bit 0,1. 1 là đã thăm, 0 là chưa thăm

Code:

Pascal (ideone)

uses    math;
const   fi='';
        fo='';
        maxn = 16;
        oo = 1 shl 16 -1;
var     f       :array[0..oo,1..maxn] of longint;
        i,j,n   :longint;
        c       :array[1..maxn,1..maxn] of longint;
        res     :longint;
procedure enter;
begin
        assign(input,fi);reset(input);
        readln(n);
        for i:=1 to n do
                for j:=1 to n do read(c[i,j]);
        close(input);
end;
function getbit( i,x :longint):byte;
begin
        getbit := (x shr (i-1)) and 1;
end;
function turnoff( i,x   :longint):longint;
begin
        turnoff := x and not (1 shl (i-1));
end;
procedure process;
var     i,j,k,t,state   :longint;
begin
        t := 1 shl n -1;
        for i:= 0 to t do
                for j:=1 to n do
                        f[i,j] := trunc(1e9);
        for i := 0 to t do
                for j := 1 to n do
                        if getbit(j,i)=1 then
                        begin
                                state := turnoff(j,i);
                                if state = 0 then begin f[i,j] := 0; break; end;
                                for k:=1 to n do
                                        if getbit(k,i)=1 then
                                                f[i,j] := min(f[i,j], f[state,k] + c[k,j]);
                        end;
        res := trunc(1e9);
        for i:=1 to n do
                res := min(res, f[t,i]);
end;
procedure print;
begin
        assign(output,fo);rewrite(output);
        writeln(res);
        close(output);
end;
begin
        enter;
        process;
        print;
end.

C++ (ideone)

#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--)
const int maxn = 1e5 ;
const int base = 1e9 + 7;
const int maxa = 1e6 * 5 + 1;
const int N = 50;
using namespace std;
int n,a[N][N],f[maxn][N],t[N],ans;

int get(int x,int i)
{
    return (x>>(i-1))&1;
}

int off(int x,int i)
{
    return x ^ (1<<(i-1));
}

int main()
{
    ios_base::sync_with_stdio(0);cin.tie(0);
    //freopen("trip.INP","r",stdin);
    //freopen("trip.OUT","w",stdout);
    cin>>n;
    fore(i,1,n)
    fore(j,1,n) cin>>a[i][j];
    int xx = (1< f[x1][t[j]] + a[t[j]][t[i]])
                f[x][t[i]] = f[x1][t[j]] + a[t[j]][t[i]];
            //if (x == 36)
                //cout<