标签归档:洛谷

洛谷 P3383 【模板】线性筛素数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
int n, m;
bool prime[10000005];

int main(){
    memset(prime, true, sizeof(prime));
    cin >> n >> m;
    prime[0] = prime[1] = false;
    for (int i = 2; i <= n; i++) {
        if (!prime[i])continue;
        for (int j = 2 * i; j <= n; j += i) {
            prime[j] = false;
        }
    }
    for (int i = 1; i <= m; i++) {
        int tmp;
        cin >> tmp;
        cout << (prime[tmp]?"Yes":"No") << endl;
    }
}

洛谷 P3367 【模板】并查集

明明记得之前应该有并查集的板子在博客里?怎么找不到了??

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
int father[10005];
int _find(int num) {
    if (father[num] == -1)return num;
    else return father[num] = _find(father[num]);
}
void _union(int v1, int v2) {
    if (_find(v1) == _find(v2))return;
    father[_find(v2)] = v1;
}
int n, m;
int main(){
    memset(father, -1, sizeof(father));
    cin >> n >> m;
    while (m--) {
        int z, x, y;
        cin >> z >> x >> y;
        if (z == 1)_union(x, y);
        else cout << (_find(x) == _find(y) ? 'Y' : 'N') << endl;
    }
}

洛谷 P1020 导弹拦截

又是自己改了半天的一道题,忘了……

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int n=1;
int arr[100005];
int f[100005];
int f2[100005];
int main() {
    while (cin >> arr[n])n++;
    n--;
    arr[0] = 50001;
    f[0] = 0;
    for (int i = 1; i <= n; i++) {
        int m = f[0];
        for (int j = 1; j < i; j++) {
            if (f[j]>m&&arr[j]>=arr[i]) {
                m = f[j];
            }
        }
        f[i] = m + 1;
    }
    cout << *max_element(f+1,f+n+1) << endl;
    arr[0] = 0;
    f2[0] = 0;
    for (int i = 1; i <= n; i++) {
        int m = f2[0];
        for (int j = 1; j < i; j++) {
            if (f2[j]>m&&arr[j]<arr[i]) {
                m = f2[j];
            }
        }
        f2[i] = m + 1;
    }
    cout << *max_element(f2+1,f2+n+1) << endl;
}

洛谷 P1233 木棍加工

不好做啊……想不出来……看题解……

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int n;
struct node {
    int l, w;
    bool operator < (const node& n2) const {
        if (l != n2.l)return l > n2.l;
        if (w != n2.w)return w > n2.w;
        return false;
    }
}arr[5005];
bool visited[5005];
int main() {
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> arr[i].l >> arr[i].w;
    }
    sort(arr + 1, arr + n + 1);
    bool flag = false;
    int cnter = 0, ptr = 0;
    do {
        flag = false;
        for (ptr=1;ptr <= n; ptr++) {
            if (!visited[ptr]) {
                flag = true;
                visited[ptr] = true;
                break;
            }
        }
        if (!flag)break;
        cnter++;
        for (int i = ptr+1; i <= n; i++) {
            if (visited[i] || arr[i].l > arr[ptr].l || arr[i].w > arr[ptr].w) continue;
            visited[i] = true;
            ptr = i;
        }
    } while (flag);
    cout << cnter;
}

洛谷 P1080 国王游戏

这题不好写,一个问题在贪心怎么排序,再有的难点就是高精乘/除,都不好写。。
这次正经的写了个高精度乘/除。。留下来备用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int n;
struct bigInt { //For Non-negative Numbers
private:
    string v;
    static string & bIsort(string & v) { //each char has reduced '0'
        for (int i = 0; i < v.length(); i++) {
            if (v[i] > 9) {
                if (i == v.length() - 1)v.append(1, v[i] / 10);
                else v[i + 1] += v[i] / 10;
                v[i] %= 10;
            }
        }
        return v;
    }
    static string lng2str(long long v) {
        string s = "";
        while (v) {
            s.append(1, v % 10 + '0');
            v /= 10;
        }
        reverse(s.begin(), s.end());
        return s;
    }
    static string& trimPre0(string& v3) {
        while (v3.length() != 0 && (*v3.begin()) == '0')v3.erase(v3.begin());
        if (v3.length() == 0)v3 = "0";
        return v3;
    }
public:
    bigInt() {
        v = "0";
    }
    bigInt(long long n) {
        v = lng2str(n);
    }
    bigInt(string s) {
        v = s;
    }
    bigInt& operator = (const bigInt & bI) {
        this->v = bI.v;
        return *this;
    }
    bigInt operator * (bigInt bI2) const {
        string v1 = v, v2 = bI2.v;
        if (v2.length() > v1.length())swap(v1, v2);
        reverse(v1.begin(), v1.end());
        reverse(v2.begin(), v2.end());
        string v3 = "";
        for (int i = 0; i < v1.length(); i++)v1[i] -= '0';
        for (int i = 0; i < v2.length(); i++)v2[i] -= '0';
        v3.resize(v1.length() + v2.length(), 0);
        for (int i = 0; i < v2.length(); i++) {
            for (int j = 0; j < v1.length(); j++) {
                v3[i + j] += v2[i] * v1[j];
            }
            bIsort(v3);
        }
        for (int i = 0; i < v3.length(); i++)v3[i] += '0';
        reverse(v3.begin(), v3.end());
        trimPre0(v3);
        return bigInt(v3);
    }
    bigInt operator / (long long bI2) const {
        string v1 = v;
        for (int i = 0; i < v1.length(); i++)v1[i] -= '0';
        long long v2 = bI2;
        string v3 = "";
        long long div = 0;
        for (int i = 0; i < v1.length(); i++) {
            div *= 10;
            div += v1[i];
            if (div < v2) {
                v3.append(1, '0');
                continue;
            }
            v3.append(lng2str(div / v2));
            div %= v2;
        }
        return bigInt(trimPre0(v3));
    }
    bool operator < (bigInt bI2) const {
        if (v.length() != bI2.v.length())return v.length() < bI2.v.length();
        for (int i = 0; i < v.length(); i++) {
            if (v[i] != bI2.v[i])return v[i] < bI2.v[i];
        }
        return false;
    }
    friend istream& operator >> (istream& in, bigInt& bI) {
        in >> bI.v;
        return in;
    }
    friend ostream& operator << (ostream& out, bigInt& bI) {
        out << bI.v;
        return out;
    }
};
struct p {
    bigInt a;
    int b;
    bool operator < (const p& p2) {
        return a * b < p2.a*p2.b;
    }
}ps[1005];

int main() {
    cin >> n;
    for (int i = 1; i <= n + 1; i++) {
        cin >> ps[i].a >> ps[i].b;
    }
    sort(ps + 2, ps + n + 2);
    bigInt multiply = ps[1].a;
    bigInt mmax("0");
    for (int i = 2; i <= n + 1; i++) {
        mmax = max(mmax, multiply / ps[i].b);
        multiply =multiply* ps[i].a;
    }
    cout << mmax;
}

洛谷 P1338 末日的传说

可以说是超难的一道题了。。。。
全程题解:
https://www.luogu.org/blog/user11765/solution-p1338

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include<iostream>
#include<algorithm>
using namespace std;
long long n, m, a[50005];
int main() {
    cin >> n >> m;
    long long s = 1, e = n;
    for (long long i = 1; i <= n; i++) {
        long long t = (n - i)*(n - i - 1) / 2;
        if (t >= m)a[s++] = i;
        else {
            a[e--] = i;
            m -= e - s + 1;
        }
    }
    for (int i = 1; i <= n; i++)cout << a[i] << " ";
}

洛谷 P1582 倒水 题解

题目描述
一天,CC买了N个容量可以认为是无限大的瓶子,开始时每个瓶子里有1升水。接着~~CC发现瓶子实在太多了,于是他决定保留不超过K个瓶子。每次他选择两个当前含水量相同的瓶子,把一个瓶子的水全部倒进另一个里,然后把空瓶丢弃。(不能丢弃有水的瓶子)

显然在某些情况下CC无法达到目标,比如N=3,K=1。此时CC会重新买一些新的瓶子(新瓶子容量无限,开始时有1升水),以到达目标。

现在CC想知道,最少需要买多少新瓶子才能达到目标呢?

输入输出格式
输入格式:
一行两个正整数, N,K。

输出格式:
一个非负整数,表示最少需要买多少新瓶子。

这道题很有意思,所以要在这里好好的写一下题解。

由“开始时每个瓶子里有1升水”和“新瓶子容量无限,开始时有1升水”、“他选择两个当前含水量相同的瓶子,把一个瓶子的水全部倒进另一个里”,很容易联想到但凡不是空瓶子,每个瓶子里水的数量一定都是以2为底的幂,如1、2、4、8、16、32、64……等等。由此我们可以将这些数字放到二进制视角下来思考。

由题中说“他决定保留不超过K个瓶子”,可将其转化为“CC最终所具有的瓶子总数 n_f 在二进制表示形式下有总计不超过K个1”。
(下面说的所有东西可能都不太好想,请认真思考。)

然而我们需要买空瓶子……所以结果的数字只能大不能小,因此我们需要通过去除数字末尾的1,保留数字前面的1来使数字达到要求。

除了Lowbit之外,我还有一种做法(这个做法其实就是Lowbit和加综合起来的底层实现)。这个做法分为三步:
1、找到数字中倒数第一个1.
2、把接下来从后向前连续的所有1变成0.
3、再把接下来不是1的第一个0变成1.
举例:原数:001011
第二步完成后:001000
第三步完成后:001100
重复进行这一操作,直到满足要求“瓶子总数 n_f 在二进制表示形式下有总计不超过K个1”即可。

程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<deque>
#include<map>
#include<cstring>
using namespace std;
inline int & setBit(int & v, int sv, int p) {
    if (sv) {
        v |= 1 << p;
    }
    else {
        v &= ~(1 << p);
    }
    return v;
}
inline int getBit(int v, int p) {
    return (v >> p) & 1;
}
bool checkBits(int value, int num) {
    int cnt = 0;
    for (int i = 0; i < 32; i++) {
        cnt += getBit(value, i);
    }
    return cnt <= num;
}
int main() {
    int n, k;
    cin >> n >> k;
    int no = n;
    while (!checkBits(n, k)) {
        int ptr = 0;
        while (!getBit(n, ptr))ptr++;
        while (getBit(n, ptr)) {
            setBit(n, 0, ptr);
            ptr++;
        }
        setBit(n, 1, ptr);
    }
    cout << n-no;
}

洛谷 P1164 小A点菜

这动规没见过,不好做……参考题解了……
https://www.luogu.org/blog/DEDSECspace/solution-p1164
https://www.luogu.org/blog/6-28318530717958/solution-p1164

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<deque>
#include<map>
#include<cstring>
using namespace std;
int n, m;
int A[105];
int f[10005];
int main() {
    cin >> n >> m;
    for (int i = 1; i <= n; i++)cin >> A[i];
    f[0] = 1;
    for (int i = 1; i <= n; i++) {
        for (int j = m; j >= A[i]; j--) {
            f[j]+= f[j - A[i]];
        }
    }
    cout << f[m];
}

洛谷 P1060 开心的金明

Ver1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<deque>
#include<map>
#include<cstring>
using namespace std;
int n, m;
int v[30],w[30];//乘积,价格
int f[30][30005]; //物品,钱数
int main() {
    cin >> n >> m;
    for (int i = 1; i <= m; i++) {
        int tmp2;
        cin >> w[i] >> tmp2;
        v[i] = w[i] * tmp2;
    }
    for (int i = 1; i <= m; i++) {
        for (int j = 0; j <= n; j++) {
            if(j>=w[i])f[i][j] = max(f[i - 1][j], f[i - 1][j - w[i]] + v[i]);
            else f[i][j] = f[i - 1][j];
        }
    }
    int mmax = 0;
    for (int i = 0; i <= n; i++) {
        mmax = max(mmax, f[m][i]);
    }
    cout << mmax;
}

Ver2:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<deque>
#include<map>
#include<cstring>
using namespace std;
int n, m;
int v[30],w[30];//乘积,价格
int f[30005]; //钱数
int main() {
    cin >> n >> m;
    for (int i = 1; i <= m; i++) {
        int tmp2;
        cin >> w[i] >> tmp2;
        v[i] = w[i] * tmp2;
    }
    for (int i = 1; i <= m; i++) {
        for (int j = n; j >=w[i]; j--) {
            f[j] = max(f[j], f[j - w[i]] + v[i]);
        }
    }
    int mmax=0;
    for (int i = 0; i <= n; i++) {
        mmax = max(mmax, f[i]);
    }
    cout << mmax;
}

洛谷 P1030 求先序排列

这类型的题(给中序和前后任一个,让求另外一个的)已经做了不下3、4遍了。。
再贴出来,代码风格可能会不大一样。。。应该是相比之前的有很多改进的。。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<deque>
#include<map>
#include<cstring>
using namespace std;

struct node {
    char l, r;
    node() {
        l = r = '*';
    }
    node(char l1, char r1) {
        l = l1;
        r = r1;
    }
};
map<char, node> dic;

string in, post;

inline int searchInTraversal(char v, int s, int e) {
    for (int i = s; i <= e; i++)if (in[i] == v)return i;
    return -1;
}
char buildTree(int is, int ie,int ps,int pe) {
    char father = post[pe];
    if (is == ie && ps == pe) {
        dic[father] = node();
        return father;
    }
    if (is > ie || ps > pe) {
        return '*';
    }
    int posOfF = searchInTraversal(father, is, ie);
    int lTreeLen = posOfF - is;
    char l = buildTree(is, posOfF - 1, ps, ps + lTreeLen - 1);
    char r = buildTree(posOfF + 1, ie, ps + lTreeLen, pe - 1);
    dic[father] = node(l, r);
    return father;
}
void preTraversal(char node) {
    if (node == '*')return;
    cout << node;
    preTraversal(dic[node].l);
    preTraversal(dic[node].r);
}

int main() {
    cin >> in >> post;
    char f=buildTree(0, in.length() - 1, 0, post.length() - 1);
    preTraversal(f);
}