1. 程式人生 > >zzuli 第九屆ACM校賽題解

zzuli 第九屆ACM校賽題解

“玲瓏杯”鄭州輕工業學院第九屆ACM程式設計大賽暨河南高校邀請賽-正式賽

Problem A: tmk射氣球

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 575  Solved: 106

SubmitWeb Board

Description

有一天TMK在做一個飛艇環遊世界,突然他發現有一個氣球勻速沿直線飄過,tmk想起了他飛艇上有一把弓,他打算拿弓去射氣球,為了提高射擊的準確性,他首先在飛艇上找到一個離氣球最近的一個點,然後射擊(即使氣球在飛船的正上方),現在求某些時刻飛艇上的點和氣球的距離最小是多少(這個最小距離我們簡稱為飛艇到氣球的距離)。

Input

第一行一個整數T(T<=20),表示有T組測試資料

每組測試資料,有兩行。

第一行有5個整數,h,x1,y1,x2,y2,其中h表示飛船的高度,飛船可抽象為一個線段,(x1,y1)(x2,y2)分別是這個線段的端點(有可能會有(x1,y1)(x2,y2)重合的情況)

第二行有6個整數,x,y,z,X,Y,Z分別表示氣球的在第0秒的時候的橫座標,縱座標,高度,一秒時間氣球橫座標的變化量,一秒時間氣球縱座標的變化量,一秒時間氣球高度的變化量(如果現在氣球在(x0,y0,z0)下一秒座標就為(x0+X,y0+Y,z0+Z))

第三行1個整數n,表示詢問組數

接下來的n行,每行一個整數,表示詢問的秒數t

題目涉及的整數除了T以外,範圍均為[0,1000]

Output

每組詢問輸出n行,每行輸出一個數,表示在t秒的時候飛艇與氣球的距離最小是多少,保留兩位小數

Sample Input

1 1 1 1 2 2 0 0 0 4 4 4  2 0 3

Sample Output

1.73 17.92

HINT


解析:三個點建一個三角形,然後如下圖,一共就三種情況,a代表飛船,b、c代表飛船到氣球的兩條邊,圖1是線段右端點距離氣球近(角C是鈍角),輸出b,圖2是左端點距離近(角B是鈍角),輸出c,圖3是輸出h,下面分別模擬這三種情況就好,比較坑的是要用double,用int分開的每一個計算都要*1.0,不然WA


程式碼:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<map>
#include<cmath>
#include<string>
#define N 1000009
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;

int main()
{
    int t;
    cin >> t;
    while(t--)
    {
        double h, x1, x2, y1, y2, x, y, z, X, Y, Z;
        int n, T;
        scanf("%lf%lf%lf%lf%lf", &h, &x1, &y1, &x2, &y2);
        scanf("%lf%lf%lf%lf%lf%lf", &x, &y, &z, &X, &Y, &Z);
        scanf("%d", &n);
        while(n--)
        {
            scanf("%d", &T);
            double xx, yy, zz;
            xx = x + X*T; yy = y + Y*T; zz = z + Z*T;
            if(abs(x1-x2)==0&&abs(y1-y2)==0)
            {
                printf("%.2f\n", sqrt(1.0*(x1-xx)*(x1-xx) + (y1-yy)*(y1-yy) + (h-zz)*(h-zz)));
                continue;
            }

            double p, a, b, c;
            a = sqrt(1.0*(x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
            b = sqrt(1.0*(x1-xx)*(x1-xx) + (y1-yy)*(y1-yy) + (h-zz)*(h-zz));
            c = sqrt(1.0*(xx-x2)*(xx-x2) + (yy-y2)*(yy-y2) + (zz-h)*(zz-h));
            p = (a + b + c) / 2.0;
            double s = sqrt(p*(p-a)*(p-b)*(p-c));
            double C = a*a+b*b-c*c;
            if(C < 0)
            {
                printf("%.2f\n", b);
                continue;
            }
            double B = a*a+c*c-b*b;
            if(B < 0)
            {
                printf("%.2f\n", c);
                continue;
            }
            printf("%.2f\n", s*2.0/a);
        }
    }
    return 0;
}

Problem B: base64解密

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 348  Solved: 153

SubmitWeb Board

Description

碼值

字元

碼值

字元

碼值

字元

碼值

字元

碼值

字元

碼值

字元

碼值

字元

碼值

字元

0

A

8

I

16

Q

24

Y

32

g

40

o

48

w

56

4

1

B

9

J

17

R

25

Z

33

h

41

p

49

x

57

5

2

C

10

K

18

S

26

a

34

i

42

q

50

y

58

6

3

D

11

L

19

T

27

b

35

j

43

r

51

z

59

7

4

E

12

M

20

U

28

c

36

k

44

s

52

0

60

8

5

F

13

N

21

V

29

d

37

l

45

t

53

1

61

9

6

G

14

O

22

W

30

e

38

m

46

u

54

2

62

+

7

H

15

P

23

X

31

f

39

n

47

v

55

3

63

/

   Base64編碼要求把3個8位位元組(3*8=24)轉化為4個6位的位元組(4*6=24),之後在6位的前面補兩個0,形成8位一個位元組的形式。 如果剩下的字元不足3個位元組,則用0填充,輸出字元使用'=',因此編碼後輸出的文字末尾可能會出現1或2個'='。

為了保證所輸出的編碼位可讀字元,Base64制定了一個編碼表,以便進行統一轉換。編碼表的大小為2^6=64,這也是Base64名稱的由來。

如對字元’0’進行Base64加密,則是如下步驟:

字元’0’的二進位制為00110000,前六位拿出來,前面補兩個0則是00001100,對應表得字元M。後面不足6位,只有兩位0,拿出來,前面補6個0,則是00000000,對應表得字元A。

由於還有2個6位的位元組沒顯示,則用兩個=字元補充

那麼字元0的Base64編碼為MA==

現在蛋蛋給了你一段加密後的Base64密文,他說題意隱藏在密文裡面,如果你知道了題意,就肯定可以做出本題。密文如下:

d2hhdCBpcyB0aGUgcmVtYWluZGVyIHdoZW4gdGhlIG51bWJlciBpcyBkaXZpZGVkIGJ5IDIwMTc/

Input

第一行一個整數t,代表有t組資料,每組資料輸入一個整數x,0<=x<=2^31-1

Output

輸出一個整數x,x為答案

Sample Input

3 0 1 2016

Sample Output

0 1 2016

HINT

解析:直接%2017

程式碼:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<map>
#include<cmath>
#include<string>
#define N 1000009
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;


int main()
{
    int x, t;
    cin >> t;
    while(t--)
    {
        scanf("%d", &x);
        printf("%d\n", x % 2017);
    }
    return 0;
}


Problem C: DOBRI

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 510  Solved: 174

SubmitWeb Board

Description

給出一個包含N個整數的序列A,定義這個序列A的字首和陣列為SUM陣列 ,當SUM陣列中的第i個元素等於在i前面的三個元素的和,那麼第i個元素就稱為GOOD。 那麼這個SUM陣列中包含多少個GOOD 元素?

Input

第一行整數T表示資料組數(1<=T<=10)

每組資料以下格式:

輸入的第一行包含一個整數N (1<=N<=100000), 表示序列A的長度。

輸入的第二行包含N個用空格隔開的整數,表示序列A (-100000<=Ai<=100000).

Output

每組資料輸出僅一行,輸出這個SUM陣列中包含多少個GOOD元素。

Sample Input

3 4 1 1 1 3 4 1 2 3 10 6 5 -2 -3 1 3 3

Sample Output

1 0 1

HINT

解析:遍歷一遍,記錄字首和陣列sum[N] 前三個的和等於當前數的個數

程式碼:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<map>
#include<cmath>
#include<string>
#define N 1000009
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;


int sum[N];

int main()
{
    int t, n, num;
    cin >> t;
    while(t--)
    {
        scanf("%d", &n);
        sum[0] = 0;
        for(int i = 1; i <= n; i++)
        {
            scanf("%d", &num);
            sum[i] = num + sum[i - 1];
        }
        int ans = 0;
        for(int i = 4; i <= n; i++)
        {
            if(sum[i] == sum[i-1]+sum[i-2]+sum[i-3]) ans++;
        }
        printf("%d\n", ans);
    }
    return 0;
}


Problem D: hipercijevi

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 644  Solved: 122

SubmitWeb Board

Description

在遙遠的星系, 最快的交通方式是用某種管道。 每個管道直接互相連線N個站。 那麼我們從第一個站到第N個站最少要經過多少個站呢?

Input

輸入檔案的第一行為T表示有T組資料

每個資料第一行包含三個正整數 N (1<=N<=100000) 表示站的個數; K (1<=K<=1000) 表示一個管道直接連線了多少個站; M (1<=M<=1000) 表示管道的數量。

接下來的M行, 每行包含一個管道的描述: K個正整數, 表示這個管道連線的K個站的編號。

Output

輸出檔案T行,每行包含一個正整數,表示從第一個站到第N個站最少需要經過多少個站。 如果無法從第一個站到達第N個站,輸出-1 。

Sample Input

2 9 3 5 1 2 3 1 4 5 3 6 7 5 6 7 6 8 9 15 8 4 11 12 8 14 13 6 10 7 1 5 8 12 13 6 2 4 10 15 4 5 9 8 14 12 11 12 14 3 5 6 1 13

Sample Output

4 3

HINT

解析:每條管道建立一個點,把管道中的所有點連一下,然後BFS一遍,結果  / 2 + 1(管道也算一個點了,所以要除2),如果mp[N][N] 10^10必然爆棧,這裡用到鏈式前向星,由於資料比較多,需要要到輸入掛,自己百度

程式碼:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<map>
#include<cmath>
#include<string>
#define N 2000009
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;

struct node
{
    int to, nxt;
}p[N];

int cnt, head[N], vis[N], n;

void add(int u, int v)
{
    p[cnt].to = v;
    p[cnt].nxt = head[u];
    head[u] = cnt++;
}

typedef pair<int, int> P;

int bfs()
{
    queue<P> q;
    q.push((P){1, 0});
    memset(vis, 0, sizeof(vis));
    vis[1] = 1;
    while(!q.empty())
    {
        P s = q.front(); q.pop();
        if(s.first == n) return s.second / 2 + 1;
        for(int i = head[s.first]; i != -1; i = p[i].nxt)
        {
            if(vis[p[i].to]) continue;
            vis[p[i].to] = 1;
            q.push((P){p[i].to, s.second + 1});
        }
    }
    return -1;
}


inline void q_read(int &num)
{
    int f = 1;
    char ch;
    while(true)
    {
        ch = getchar();
        if(ch == '-') f = -1;
        if(isdigit(ch))
        {
            num = ch - '0';
            break;
        }
    }
    while(ch = getchar(), isdigit(ch)) num = num*10 + ch - '0';
    num *= f;
}


int main()
{
    int t, k, m, from, to;
    q_read(t);
    while(t--)
    {
        memset(head, -1, sizeof(head));
        cnt = 0;
        q_read(n); q_read(k); q_read(m);
        for(int i = 1; i <= m; i++)
        {
            from = n + i;
            for(int j = 1; j <= k; j++)
            {
                q_read(to);
                add(from, to);
                add(to, from);
            }
        }
        printf("%d\n", bfs());
    }
    return 0;
}



Problem E: Can Win

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 335  Solved: 42

SubmitWeb Board

Description

Zhc很喜歡看某個競技比賽,比賽的規則是這樣的:隊伍分成AB兩組進行比賽,除了組內比賽,兩組之間還會進行一定的比賽,每場比賽贏者得1分,輸者不得分,沒有平局的情況。 在A組裡面Zhc有一支自己非常喜歡的隊伍,現在比賽已經進行到一半了,Zhc想知道,他支援的那支隊伍有沒有可能獲得最終的勝利(A組最高分即為勝利,允許多支隊伍同時最高分)

Input

 第一行輸入樣例組數T<=110

每組樣例第一行輸入A組隊伍數量n<=400,以及Zhc支援的隊伍編號(1-n)K<=n

第二行按編號輸入A組各隊伍目前的成績Mark[i]<= 300000

第三行按編號輸入A組各隊伍剩餘比賽總場數Cnt[i]<= 300000

下面有一個N*N的矩陣,其中A[i][j]代表編號i的隊伍跟編號j的隊伍剩餘比賽場數A[i][j]<=100

Output

 對每組樣例輸出”Yes”或者”No”(不用輸出引號)代表Zhc支援的隊伍能獲得最終的勝利,換行處理

Sample Input

1 2 1 5 6 2 2 0 1 1 0

Sample Output

Yes

解析:


程式碼:

#include<bits/stdc++.h>
#define M 2000009
#define N 160010
#define maxn 409
using namespace std;
const int INF = 0x3f3f3f3f;

int n, kk;
int win[maxn], fight[maxn][maxn], Max;


inline void q_read(int &num)
{
    int f = 1;
    char ch;
    while(true)
    {
        ch = getchar();
        if(ch == '-') f = -1;
        if(isdigit(ch))
        {
            num = ch - '0';
            break;
        }
    }
    while(ch = getchar(), isdigit(ch)) num = num * 10 + ch - '0';
    num *= f;
}



struct Edge{
    int u, v, cap, flow, next;
}E[M];

struct Dinic{
    int head[N], d[N], iter[N];
    int tot, sink, source;

    void init() {
        memset(head, -1, sizeof(head));
        tot = 0;
    }

    inline void AddEdge(int u, int v, int cap) {
        E[tot].u = u; E[tot].v = v; E[tot].cap = cap; E[tot].flow = 0; E[tot].next = head[u]; head[u] = tot++;
        u = u ^ v; v = u ^ v; u = u ^ v;
        E[tot].u = u; E[tot].v = v; E[tot].cap = 0; E[tot].flow = 0; E[tot].next = head[u]; head[u] = tot++;
    }

    inline bool bfs(int s) {
        int u, v;
        memset(d, 0, sizeof(d));
        queue<int> Q;
        Q.push(s);
        d[s] = 1;
        while (!Q.empty()) {
            u = Q.front(); Q.pop();
            if (u == sink) return true;
            for (int i = head[u]; ~i; i = E[i].next) {
                v = E[i].v;
                if (!d[v] && E[i].cap - E[i].flow > 0) {
                    d[v] = d[u] + 1;
                    Q.push(v);
                }
            }
        }
        return false;
    }

    int dfs(int x, int a) {
        if (x == sink || a == 0)
            return a;
        int f, flow = 0;
        for (int i = head[x]; ~i; i = E[i].next) {
            int v = E[i].v;
            if (d[v] == d[x] + 1 && E[i].cap - E[i].flow > 0) {
                f = dfs(v, min(a, E[i].cap - E[i].flow));
                E[i].flow += f;
                E[i^1].flow -= f;
                flow += f;
                a -= f;
                if (!a) break;
            }
        }
        if (flow == 0) d[x] = 0;
        return flow;
    }

    int Maxflow(int source, int sink) {
        int flow = 0;
        this->sink = sink;
        //memcpy(iter, head, sizeof head);
        while (bfs(source)) flow += dfs(source, INF);
        return flow;
    }
}dinic;


int init() {
    //scanf("%d %d", &n, &kk);
    q_read(n); q_read(kk);
    Max = -INF;
    int t;
    for (int i = 1; i <= n; i++) {
        //scanf("%d", &win[i]);
        q_read(win[i]);
        Max = max(Max, win[i]);
    }
    int total = win[kk];
    for(int i = 1; i <= n; i++)
    {

        //scanf("%d", &t);
        q_read(t);
        if(i == kk) total += t;
    }

    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++) {
            //scanf("%d", &fight[i][j]);
            q_read(fight[i][j]);
        }
    return total;
}

void solve(int total) {
    //bool flag = false;
    int source = 0, sink =  N - 1, cnt;

    if (total < Max)
    {
        puts("No");
        return ;
    }

    cnt = n + 1;
    dinic.init();
    int Sum = 0;
    for (int j = 1; j <= n; j++)
    {
        if(j == kk) continue;
        dinic.AddEdge(j, sink, total - win[j]);
        for (int k = j + 1; k <= n; k++)
        {
            if (k == kk) continue;
            dinic.AddEdge(source, cnt, fight[j][k]);
            Sum += fight[j][k];
            dinic.AddEdge(cnt, j, fight[j][k]);
            dinic.AddEdge(cnt++, k, fight[j][k]);
        }
    }
    int MaxFlow = dinic.Maxflow(source, sink);
    if (MaxFlow == Sum) puts("Yes");
    else puts("No");

}

int main() {
    int test;
    scanf("%d", &test);
    while (test--) {
        int total = init();
        solve(total);
    }
    return 0;
}


Problem F: Tmk吃湯飯

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 451  Solved: 193

SubmitWeb Board

Description

Tmk喜歡吃湯飯!

Tmk喜歡吃湯飯!!

Tmk喜歡吃湯飯!!!

湯飯視窗分點餐和取餐兩個視窗,一位蜀黍負責點餐視窗,一位蜀黍負責煮湯,一位蜀黍負責打飯,點餐需要1個單位時間,每一份需要煮5個單位時間,同一時間最多可以煮4份。

現在tmk要考考你,給你所有人的到達時刻,每個人在到達時刻排到點餐佇列的末尾,點完餐後排到取餐佇列,煮好後即可取餐,問你最後一個人取到湯飯的時間。

除了點餐和煮湯的時間,其他時間忽略不計,沒人插隊,而且他們意志堅定,所以不會中途而廢,每個湯飯必須連續煮,不能中斷。

Input

第一行一個T(0<T<=100),表示有多少組資料。

對於每組資料:

第一行一個整數n(0<=n<=100000)表示有n個人。

第二行,n個整數,以空格隔開(其中t[i]>=0 && t[i] < 50000000 && t[i] > t[i-1]),t[i]表示第i個人的到達時刻。

Output

對於每個樣例,輸出最後一個人取到湯飯的時間。

Sample Input

2 3 4 5 6 5 2 3 4 5 6

Sample Output

12 13

HINT


解析:用佇列一直模擬,佇列中如果>=4需要把最前面的出隊,然後如果後面還有人,取max(該人到來時間+1,佇列最小值+5)入隊,一直模擬即可

程式碼:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<map>
#include<cmath>
#include<string>
#define N 1000009
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;

int a[N];

queue<int> q;

int main()
{
    int t;
    scanf("%d", &t);
    while(t--)
    {
        int n, T = 0;
        scanf("%d", &n);
        for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
        for(int i = 1; i <= n; i++)
        {
            if(q.size() >= 4)
            {
                T = max(q.front() + 5, a[i] + 1);
                q.pop();
                q.push(T);
                continue;
            }
            q.push(a[i] + 1);
        }
        while(!q.empty())
        {
            T = max(T, q.front()+5);
            q.pop();
        }
        printf("%d\n", T);
    }
    return 0;
}


Problem G: 密室逃脫

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 296  Solved: 48

SubmitWeb Board

Description

XOR在玩密室逃脫,在某一關中,桌上有一個一張紙,上面寫著“請根據所給例子求解答案從而獲得密碼”,下面寫了幾個字串“01 10 11”,而答案為“6”,聰明的XOR立馬就知道了這是給出一些二進位制數字S,求存在多少對有序二元組(i,j)使得S[i]^S[j]<S[i],現在還有T組資料,每組是n個長度為m的二進位制數字,聰明的XOR立馬開始動手求解答案。

Input

第一行一個整數T,表示資料組數。

對於每組資料,首先讀入兩個整數n,m(n*m<=1000000),接下來為n行,每行為一個長度為m的01串,表示一個二進位制數字

Output

對於每個資料,輸出一個整數x,表示二元組數目

Sample Input

1 3 2 01 10 11

Sample Output

6

HINT

解析:可以發現 a^b 與 a 的大小隻與 b 的二進位制表示中最高位的 1 所在的那一位有關,如果 a 在
這一位是 0,a^b>a,否則 a^b<a,那麼就我們只要考慮每一位中有多少個數在這一位是 1 和多少
個數的最高位 1 是這一位,將它們相乘後累加即可,時間複雜度為 O(n*m+m)

程式碼:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<map>
#include<cmath>
#include<string>
#define N 1000009
using namespace std;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;

long long a[N], b[N];
char s[N];


int main()
{
    int t, n, m;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d%d", &n, &m);
        memset(a, 0, sizeof(a));
        memset(b, 0, sizeof(b));
        int k = -INF;
        k = max(k, m);
        while(n--)
        {
            scanf(" %s", s);
            int f = 1;
            for(int i = 0; i < m; i++)
            {
                if(s[i] == '1' && f) a[m - i]++, f = 0;
                if(s[i] == '1') b[m - i]++;
            }
        }
        long long ans = 0;
        for(int i = 1; i <= m; i++) ans += a[i]*b[i];
            printf("%lld\n", ans);
    }
    return 0;
}


Problem H: 維克茲的進位制轉換

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 231  Solved: 48

SubmitWeb Board

Description

我進入了突如其來的強光。閃爍。閃爍,閃爍,閃爍。我調整好眼睛,評估我前方的景觀。

有東西在亂竄。我往下看,發現了一隻小個的白色生物,用後腿站立著,嗅聞著我的軀體。它吸引了我的注意。

你有什麼用途?

我分析這個生物。品紅色熱能光束一閃而過,它曾顫動的地方揚起塵埃。

哺乳動物...夜行習性...無可挑剔的聽覺。難以置信的弱小。但它們的繁殖能力如此強大。

“唔,”我喃喃自語。希望能發現更加複雜的物體;那些東西把我給迷住了。

消化並學習:這是我的目的。和我一起旅行的其它來客都很原始:殺死並吃掉,殺死並吃掉。我需要收集所有可用的資訊——收穫更多有價值的資源。

維克茲是少數熱愛學習的虛空來客之一,他帶著非凡的意圖探索著符文之地:吸收掉所有知識。憑藉著他不斷地注視,維克茲可以發射瓦解光線來滅除並分析他途中的一切東西,併為他供給數量龐大的資訊。沒人知道他為什麼需要如此多的材料,儘管有人推測他設法瞭解符文之地,是為了加速它的毀滅。

有一天,維克茲突發奇想,他覺得古老的二進位制魔法串太過單一,於是他規定二進位制除了 0 和 1,還有 2。現在維克茲想知道該規則下十進位制數 N 轉換為二進位制數的方案數,維克茲當然可以輕鬆算出來,但他正好缺一個一起遊覽符文大地的夥伴,於是他把這個問題交給了你,希望你不要讓他失望才好。

Input

輸入包括 T 組資料,每組資料有一個非負整數 N。(T <= 1e5, N <= 1e7)

Output

輸出一個正整數代表十進位制數 N 轉換為二進位制數的方案數。

Sample Input

4 1 2 3 4

Sample Output

1 2 1 3

HINT

1 ——> 1
2 ——> 10 or 2
3 ——> 11
4 ——> 100 or 20 or 12


解析:對於一個數,我們先考慮其最後一位為 0、1、2 中的哪一個。如果 n&1,那麼最後一位只能是 1,所以 f[n] = f[n/2]。否則,那麼最後一位可以是 0 或則 2,所以 f[n]=f[n/2]+f[n/2-1]。特殊地,f[0] = 1,f[1] = 1,f[2] = 2。

程式碼:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<map>
#include<cmath>
#include<string>
#define N 10000009
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;

int f[N];

void init()
{
    f[0] = 1; f[1] = 1; f[2] = 2;
    for(int i = 3; i <= 10000000; i++)
    {
        if(i&1) f[i] = f[i/2];
        else f[i] = f[i/2] + f[i/2-1];
    }
}

int main()
{
    init();
    int t, n;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d", &n);
        printf("%d\n", f[n]);
    }
    return 0;
}



Problem I: 這裡是天堂!

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 864  Solved: 96

SubmitWeb Board

Description

Maple他打程式碼打累了,於是Maple跑去找貓貓們來拯救自己。

Maple來到了一個空房間裡,房間的隔壁是一個有很多隻貓貓的房間,在Maple的房間裡有一個按鈕,每次按一下按鈕,就會有且只有一隻貓貓從旁邊的房間裡跑過來找Maple玩,當然當隔壁房間沒有貓的時候並不會有貓貓跑過來。

Maple按了幾次按鈕後發現跑過來的貓貓只有白色和黃色兩種毛色,而且如果假設當每次按按鈕後旁邊房間剩下的貓跑過來的概率都相同,那麼Maple就開始想,如果當隔壁房間共有n只白貓和m只黃貓時,當他按了k次按鈕後,跑過來的白貓數量和黃貓數量分別為a只和b只的概率是多少。

Input

第一行有一個整數T,代表有T組資料(1<=T<=2000)

每組資料有五個整數n,m,k,a,b,其中0<=n,m,k,a,b<=10

Output

對於每組資料,得到的概率為一個分數A/B(A<=B且AB為互質整數),輸出兩個整數A、B,用一個空格分開。

Sample Input

2 1 1 1 1 0 9 1 10 9 1

Sample Output

1 2 1 1

HINT

特殊的,概率為0的分數表示法為0/1。

解析:比賽一直過不了0 1、 1 1這兩個特殊情況,就算最後給過了,爆int沒發現,以為公式錯了,就沒再寫,還是自己太菜,,, 程式碼:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<map>
#include<cmath>
#include<string>
#define N 1000009
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;


LL c_(LL m, LL n)
{
    LL a, b; a = b = 1ll;
    for(LL i = 0; i < n; i++)
    {
        a *= (m - i);
        b *= (i + 1);
    }
    return a / b;
}

int main()
{
    int t, n, m, a, b, k;
    cin >> t;
    while(t--)
    {
        scanf("%d%d%d%d%d", &m, &n, &k, &a, &b);
        if(a > m || b > n || a + b > k || (a + b < m + n && k != a + b))
        {
            printf("0 1\n");
            continue;
        }
        if(a == m && b == n && k >= a + b)
        {
            printf("1 1\n");
            continue;
        }
        k = min(k, a + b);
        LL l = c_(m, a) * c_(n, b);
        LL r = c_(m+n, k);
        LL g = __gcd(l, r);
        l /= g; r /= g;
        printf("%d %d\n", (int)l, (int)r);
    }
    return 0;
}


相關推薦

zzuli 九屆ACM題解

“玲瓏杯”鄭州輕工業學院第九屆ACM程式設計大賽暨河南高校邀請賽-正式賽 Problem A: tmk射氣球 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 575  Solved: 106SubmitWeb B

2018 年山東省九屆ACM部分題解

A題 貪心瞎搞 看第二個樣例 s:ELLY t:KRIS 先對兩個字串排序 如果s[i]<=t[i]直接轉換,否則KRS部分迴圈一下求解 1.ELLY IKRS 2.ELLY IRSK 3.ELLY ISKR 求這三種情況的最小花費

2018年山東省九屆acm F題 Four-tuples(離散數學 容斥定理)

Four-tuplesTime Limit: 2000 ms Memory Limit: 524288 KiBProblem DescriptionGiven l1, r1, l2, r2, l3, r3, l4, r4, please count the number of

容斥定理 -- 九屆ACM山東省F題 Four-tuples (SDUT4219)

Four-tuplesTime Limit: 2000 msMemory Limit: 524288 KiBOutputFor each test case, output one line containing one integer, representing the a

2018年山東省九屆acmF題,容斥原理

#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll mod=1e9+7; int main() { ll n,l1,l2,l3,l4,r1,r2,r3,r4

Game (2018山東省九屆ACM

g:題意:給你n堆石子,兩個人nim博弈,問你事先最多移走d堆石子,問能使後手必勝的移動方法有幾種。t <=5n<=1000d<=1000ai<=1000 (每堆石子數目)思路:nim的思想一出,立馬想到異或為0,因此,問題轉化為,最多移走d堆石子,使

電子科技大學九屆ACM趣味程式設計競賽第二場(正式題解

A::魔王的直播 注意23:59之後是00:00即可,找出所有迴文字元,取最近. #include <bits/stdc++.h> using namespace std; bool check(int a,int b) { int c=a%10*

福建工程學院十四屆ACMM題題解 fwt進階,手推三進制fwt

har 直接 ali 怎麽 pre += 。。 長度 個數 第九集,結束亦是開始 題意: 大致意思就是給你n個3進制的數字,讓你計算有多少對數字的哈夫曼距離等於i(0<=i<=2^m) 思路: 這個是一個防ak題,做法是要手推公式的fwt 大概就這個意

2018/11/02 ACM集訓三次周題解及自身題目優化

問題 A: 珠心算測試 題目描述 珠心算是一種通過在腦中模擬算盤變化來完成快速運算的一種計算技術。珠心算訓練, 既能夠開發智力,又能夠為日常生活帶來很多便利,因而在很多學校得到普及。 某學校的珠心算老師採用一種快速考察珠心算加法能力的測驗方法。他隨機生成一個正

“玲瓏杯”鄭州輕工業學院九屆ACM程式設計大賽暨河南高校邀請賽-正式

    2127 Problem  A tmk射氣球 幾何 2128 Problem  B base64解密 讀題 2129 Pro

ACM第二站——2018年九屆山東省省

5月6日:第九屆山東省省賽        真正的ACM比賽,懷著無比的期待和滿心的激動,終於迎來了2018年的第九屆山東省省賽,初出茅廬的我們打響的第一場“戰爭”,就著那一腔的熱血,將會隨5月6號上午九點到下午兩點的拼搏落下帷幕。從去年的十月份入門,一直拼搏到現在,說從未懈怠

長安大學第二屆ACM程式設計競賽 題解

A Count Circles 描述 Stupid Aguin feels confused while reading. The book shows following equations: 6=9 , 8=1010 , 144=75 , 69

十六屆上海大學程式設計聯賽春季暨上海高校金馬五 題解

【題目連結】 模擬。從左往右填充每一個,如果某一個格子不足,需要從右邊離他最近的有盈餘的格子裡拿一些來填充;如果某一個格子有盈餘,那麼多餘部分往右扔過去。 /******************************* Judge Result : AC ***********

nowcoder 東北林業大學12屆ACM(低年級組)-A+B

時間限制:C/C++ 1秒,其他語言2秒空間限制:C/C++ 32768K,其他語言65536K64bit IO Format: %lld 題目描述 小H最近剛剛學完電工電子,大作業是設計並製作一個帶有顯示器的加法器,由於小H比較懶,所以只設計了個位加法

13屆廣東工業大學ACML-用來作弊的藥水

連結:https://www.nowcoder.com/acm/contest/90/L來源:牛客網時間限制:C/C++ 1秒,其他語言2秒空間限制:C/C++ 32768K,其他語言65536K 64bit IO Format: %lld題目描述    在一個風雨交加的夜晚

2016河南省九屆ACM程式設計競賽【正式真題】

A題:表示式求值 時間限制:1000 ms  |  記憶體限制:65535 KB 描述 假設表示式定義為:1. 一個十進位制的正整數 X 是一個表示式。2. 如果 X 和 Y 是 表示式,則 X+Y, X*Y 也是表示式; *優先順序高於+.3. 如果 X 和 Y 是

【牛客網】埃森哲杯十六屆上海大學程式設計聯賽春季暨上海高校金馬五 題解

題目連線A.Wasserstein Distance(水題)題意:給你2行土a,b,每行都有n堆,每堆對應有a[i],b[i]克,我們可以對a中的土進行移動,移動任意堆的k克泥土到a中其他堆消耗的代價是

“師創杯”山東理工大學九屆ACM程序設計競賽

ash gcd 線段 種類 最大的 排序 回來 block 年份 A:簽到題,直接LL做 B:模擬。沒什麽好寫的 C:求k * m % n == 0最小的k,k = n / (gcd(n,m)) D:bfs E:把第一和第二棵樹hash起來,然後在第一棵樹每個節點找一下相

NYOJ 1277Decimal integer conversion (九屆河南省省

printf esp 要求 nyoj out size 個數 digi ssi XiaoMing likes mathematics, and heis just learning how to convert numbers between different bases

2018 FJUT acm b題 第二集:以後我就叫你小蛤了

else 規律 pan RM 運行時間 std 等於 AI ane 第二集:以後我就叫你小蛤了 TimeLimit:1000MS MemoryLimit:128MB 64-bit integer IO format:%lld Problem Descript