codeforces #594 div2 ABCD1F

A. Integer Points

Description

给出两组直线分别为$y=x+p[i],y=-x+q[j]$,求使得两组直线有整数交点的组合数目

Solution

奇数同奇数组合,偶数同偶数组合,最后答案为$odd1*odd2+even1*even2$

#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#if __cplusplus >= 201103L
#include <unordered_map>
#include <unordered_set>
#endif
#include <vector>
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define LONG_LONG_MAX 9223372036854775807LL
#define ll LL
using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int, int> P;
int n, m, k;
const int maxn = 1e5 + 10;
template <class T>
inline T read()
{
    int f = 1;
    T ret = 0;
    char ch = getchar();
    while (!isdigit(ch))
    {
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (isdigit(ch))
    {
        ret = (ret << 1) + (ret << 3) + ch - '0';
        ch = getchar();
    }
    ret *= f;
    return ret;
}
template <class T>
inline void write(T n)
{
    if (n < 0)
    {
        putchar('-');
        n = -n;
    }
    if (n >= 10)
    {
        write(n / 10);
    }
    putchar(n % 10 + '0');
}
template <class T>
inline void writeln(const T &n)
{
    write(n);
    puts("");
}
int main(int argc, char const *argv[])
{
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#endif
    int t = read<int>();
    while (t--)
    {
        ll o1 = 0, e1 = 0, o2 = 0, e2 = 0;
        int p = read<int>();
        for (int i = 0; i < p; i++)
        {
            int x = read<int>();
            if (x & 1)
                ++o1;
            else
                ++e1;
        }
        p = read<int>();
        for (int i = 0; i < p; i++)
        {
            int x = read<int>();
            if (x & 1)
                ++o2;
            else
                ++e2;
        }
        writeln(o1 * o2 + e2 * e1);
    }
    return 0;
}
View Code

B. Grow The Tree

Description

Gardener Alexey teaches competitive programming to high school students. To congratulate Alexey on the Teacher's Day, the students have gifted him a collection of wooden sticks, where every stick has an integer length. Now Alexey wants to grow a tree from them.

The tree looks like a polyline on the plane, consisting of all sticks. The polyline starts at the point (0,0)(0,0). While constructing the polyline, Alexey will attach sticks to it one by one in arbitrary order. Each stick must be either vertical or horizontal (that is, parallel to OXOX or OYOY axis). It is not allowed for two consecutive sticks to be aligned simultaneously horizontally or simultaneously vertically. See the images below for clarification.

Alexey wants to make a polyline in such a way that its end is as far as possible from (0,0)(0,0). Please help him to grow the tree this way.

Note that the polyline defining the form of the tree may have self-intersections and self-touches, but it can be proved that the optimal answer does not contain any self-intersections or self-touches.

给出n条线段,从坐标原点沿平行坐标轴方向依次摆放,x轴y轴交替,求最终坐标与原点的距离平方的最大值

Solution

显然,要想距离平方最大,则要使其中一维尽可能的大,那么使用最短的一半铺x轴,长的一半铺y轴贪心即可

#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#if __cplusplus >= 201103L
#include <unordered_map>
#include <unordered_set>
#endif
#include <vector>
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define LONG_LONG_MAX 9223372036854775807LL
#define ll LL
using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int, int> P;
int n, m, k;
const int maxn = 1e5 + 10;
template <class T>
inline T read()
{
    int f = 1;
    T ret = 0;
    char ch = getchar();
    while (!isdigit(ch))
    {
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (isdigit(ch))
    {
        ret = (ret << 1) + (ret << 3) + ch - '0';
        ch = getchar();
    }
    ret *= f;
    return ret;
}
template <class T>
inline void write(T n)
{
    if (n < 0)
    {
        putchar('-');
        n = -n;
    }
    if (n >= 10)
    {
        write(n / 10);
    }
    putchar(n % 10 + '0');
}
template <class T>
inline void writeln(const T &n)
{
    write(n);
    puts("");
}
int a[maxn];
int main(int argc, char const *argv[])
{
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#endif
    n = read<int>();
    ll sum = 0;
    for (int i = 0; i < n; i++)
        a[i] = read<int>(), sum += a[i];
    sort(a, a + n);
    ll t1 = 0, t2 = 0;
    for (int i = 0; i < n / 2; i++)
        t1 += a[i];
    writeln((sum - t1) * (sum - t1) + (t1 * t1));
    return 0;
}
View Code

C. Ivan the Fool and the Probability Theory

Description

Recently Ivan the Fool decided to become smarter and study the probability theory. He thinks that he understands the subject fairly well, and so he began to behave like he already got PhD in that area.

To prove his skills, Ivan decided to demonstrate his friends a concept of random picture. A picture is a field of nn rows and mm columns, where each cell is either black or white. Ivan calls the picture random if for every cell it has at most one adjacent cell of the same color. Two cells are considered adjacent if they share a side.

Ivan's brothers spent some time trying to explain that it's not how the randomness usually works. Trying to convince Ivan, they want to count the number of different random (according to Ivan) pictures. Two pictures are considered different if at least one cell on those two picture is colored differently. Since the number of such pictures may be quite large, print it modulo $10^9+7$

 

给出一个n行m列01矩阵,求满足每个点最多只有一个相邻点颜色相同的摆放情况

Solution

自己是刷表找的规律,赛后发现有巧妙的证明方法,以下简单记录大佬的证法

首先可以确认的是每行或者每列如果有两个相同颜色相邻那么剩下的行列就全部颜色都被确定了,这样的话就可以转化为一行或者一列里有多少种方法

考虑dp转移方程,dp[i][0]表示第i个位置放白色的方案书,当i-1为白色时,只能由i-2为黑色转移过来,

当i-1为黑色时,i可由i-1黑色转移,综合$dp[i][0]=dp[i-1][1]+dp[i-2][1]$

黑色也是一样,那么合并第二维可以得到转移方程$dp[i]=dp[i-1]+dp[i-2]$,初值$dp[1]=2,dp[2]=4$

这时的dp[i]不仅仅考虑了两个相同颜色相邻的情况,把黑白相间也算上了,那么黑白相间一共两种,dp[n]-2即是行的答案

对于拿掉的两种黑白相间,他们又可以看作两种颜色在列上作排列,所以有列上贡献dp[m]

综上 $res=dp[n]+dp[m]-2$

 1 #include <algorithm>
 2 #include <cctype>
 3 #include <cmath>
 4 #include <cstdio>
 5 #include <cstdlib>
 6 #include <cstring>
 7 #include <iostream>
 8 #include <map>
 9 #include <queue>
10 #include <set>
11 #include <stack>
12 #if __cplusplus >= 201103L
13 #include <unordered_map>
14 #include <unordered_set>
15 #endif
16 #include <vector>
17 #define lson rt << 1, l, mid
18 #define rson rt << 1 | 1, mid + 1, r
19 #define LONG_LONG_MAX 9223372036854775807LL
20 #define ll LL
21 using namespace std;
22 typedef long long ll;
23 typedef long double ld;
24 typedef unsigned long long ull;
25 typedef pair<int, int> P;
26 int n, m, k;
27 const int maxn = 1e5 + 10;
28 const int mod = 1e9 + 7;
29 template <class T>
30 inline T read()
31 {
32     int f = 1;
33     T ret = 0;
34     char ch = getchar();
35     while (!isdigit(ch))
36     {
37         if (ch == '-')
38             f = -1;
39         ch = getchar();
40     }
41     while (isdigit(ch))
42     {
43         ret = (ret << 1) + (ret << 3) + ch - '0';
44         ch = getchar();
45     }
46     ret *= f;
47     return ret;
48 }
49 template <class T>
50 inline void write(T n)
51 {
52     if (n < 0)
53     {
54         putchar('-');
55         n = -n;
56     }
57     if (n >= 10)
58     {
59         write(n / 10);
60     }
61     putchar(n % 10 + '0');
62 }
63 template <class T>
64 inline void writeln(const T &n)
65 {
66     write(n);
67     puts("");
68 }
69 int dp[maxn];
70 void init()
71 {
72     dp[1] = 2, dp[2] = 4;
73     for (int i = 3; i <= n; i++)
74         dp[i] = (dp[i - 1] + dp[i - 2]) % mod;
75 }
76 int main(int argc, char const *argv[])
77 {
78 #ifndef ONLINE_JUDGE
79     freopen("in.txt", "r", stdin);
80     freopen("out.txt", "w", stdout);
81 #endif
82     n = read<int>(), m = read<int>();
83     if (n < m)
84         swap(m, n);
85     init();
86     writeln((dp[n] + dp[m] - 2) % mod);
87     return 0;
88 }
View Code

D1. The World Is Just a Programming Task (Easy Version)

Description

给出一个括号序列,问任意交换序列里两个值,使得循环右移满足括号匹配的方案数最多,括号序列长度<=500

Solution

菜鸡只想到O(n^4)的做法,t到死,看题解知道公式才AC

对于一个括号序列,它的循环右移满足括号匹配的方案数等价于将‘(’算作1,‘)’算作-1的前缀和序列里最小值的个数

 

 然后在check的时候就可以降低复杂度,$O(n^3)$

  1 #include <algorithm>
  2 #include <cctype>
  3 #include <cmath>
  4 #include <cstdio>
  5 #include <cstdlib>
  6 #include <cstring>
  7 #include <iostream>
  8 #include <map>
  9 #include <queue>
 10 #include <set>
 11 #include <stack>
 12 #if __cplusplus >= 201103L
 13 #include <ext/rope>
 14 #include <unordered_map>
 15 #include <unordered_set>
 16 #endif
 17 #include <vector>
 18 #define lson rt << 1, l, mid
 19 #define rson rt << 1 | 1, mid + 1, r
 20 #define LONG_LONG_MAX 9223372036854775807LL
 21 #define ll LL
 22 using namespace std;
 23 using namespace __gnu_cxx;
 24 typedef long long ll;
 25 typedef long double ld;
 26 typedef unsigned long long ull;
 27 typedef pair<int, int> P;
 28 int n, m, k;
 29 const int maxn = 1e5 + 10;
 30 template <class T>
 31 inline T read()
 32 {
 33     int f = 1;
 34     T ret = 0;
 35     char ch = getchar();
 36     while (!isdigit(ch))
 37     {
 38         if (ch == '-')
 39             f = -1;
 40         ch = getchar();
 41     }
 42     while (isdigit(ch))
 43     {
 44         ret = (ret << 1) + (ret << 3) + ch - '0';
 45         ch = getchar();
 46     }
 47     ret *= f;
 48     return ret;
 49 }
 50 template <class T>
 51 inline void write(T n)
 52 {
 53     if (n < 0)
 54     {
 55         putchar('-');
 56         n = -n;
 57     }
 58     if (n >= 10)
 59     {
 60         write(n / 10);
 61     }
 62     putchar(n % 10 + '0');
 63 }
 64 template <class T>
 65 inline void writeln(const T &n)
 66 {
 67     write(n);
 68     puts("");
 69 }
 70 inline int check(string t)
 71 {
 72     int st = 0;
 73     for (int i = 0; i < n; i++)
 74         if (t[i] == '(')
 75             ++st;
 76         else
 77         {
 78             --st;
 79             if (st < 0)
 80                 return 0;
 81         }
 82     return 1;
 83 }
 84 string s;
 85 int q[maxn];
 86 int main(int argc, char const *argv[])
 87 {
 88 #ifndef ONLINE_JUDGE
 89     freopen("in.txt", "r", stdin);
 90     freopen("out.txt", "w", stdout);
 91 #endif
 92     ios::sync_with_stdio(false);
 93     cin.tie(0);
 94     cout.tie(0);
 95     cin >> n;
 96     cin >> s;
 97     int f = 0, maxx = 0, rx, ry;
 98     for (int i = 0; i < n; i++)
 99         for (int j = i + 1; j < n; j++)
100         {
101             swap(s[i], s[j]);
102             int minx = 1e9;
103             int p = 0;
104             for (int k = 0; k < n; k++)
105             {
106                 s[k] == '(' ? p++ : p--;
107                 q[k] = p;
108                 minx = min(minx, q[k]);
109             }
110             if (p)
111             {
112                 swap(s[i], s[j]);
113                 continue;
114             }
115             int cur = 0;
116             for (int k = 0; k < n; k++)
117                 if (q[k] == minx)
118                     ++cur;
119             if (cur > maxx)
120             {
121                 f = 1;
122                 maxx = cur;
123                 rx = i, ry = j;
124             }
125             swap(s[i], s[j]);
126         }
127     if (f)
128         cout << maxx << "
"
129              << rx + 1 << " " << ry + 1 << "
";
130     else
131         cout << "0
1 1
";
132     return 0;
133 }
View Code

F. Catowice City

Description

In the Catowice city next weekend the cat contest will be held. However, the jury members and the contestants haven't been selected yet. There are nn residents and nn cats in the Catowice, and each resident has exactly one cat living in his house. The residents and cats are numbered with integers from 1 to n, where the ii-th cat is living in the house of ii-th resident.

Each Catowice resident is in friendship with several cats, including the one living in his house. In order to conduct a contest, at least one jury member is needed and at least one cat contestant is needed. Of course, every jury member should know none of the contestants. For the contest to be successful, it's also needed that the number of jury members plus the number of contestants is equal to nn.

Please help Catowice residents to select the jury and the contestants for the upcoming competition, or determine that it's impossible to do.

给出一个左右各n个点的图,左点必和对应右点相连,且有可能和其它右点相连,求一个分配方案使得$|L cup R|=n$,且L里任一元素与R的任一元素不相连

Solution

题目可以建模为将一个有向图分成两个集合L,R,且L集合到R集合没有边相连。

对图建立有向图,忽略自环边,强连通缩点建图。

找出出度为0的强连通分量作为左点集L,那么右点集R即为S-L

特别的如果没有出度为0的分量或者仅有一个强连通分量,是没有结果的,直接puts("No")

#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#if __cplusplus >= 201103L
#include <unordered_map>
#include <unordered_set>
#endif
#include <vector>
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define LONG_LONG_MAX 9223372036854775807LL
#define ll LL
using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int, int> P;
int n, m, k;
const int maxn = 1e6 + 10;
template <class T>
inline T read()
{
    int f = 1;
    T ret = 0;
    char ch = getchar();
    while (!isdigit(ch))
    {
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (isdigit(ch))
    {
        ret = (ret << 1) + (ret << 3) + ch - '0';
        ch = getchar();
    }
    ret *= f;
    return ret;
}
template <class T>
inline void write(T n)
{
    if (n < 0)
    {
        putchar('-');
        n = -n;
    }
    if (n >= 10)
    {
        write(n / 10);
    }
    putchar(n % 10 + '0');
}
template <class T>
inline void writeln(const T &n)
{
    write(n);
    puts("");
}
struct node
{
    int to, nxt;
} edg[maxn];
int head[maxn], dfn[maxn], low[maxn], scc[maxn], vis[maxn], tot, scc_num, cnt;
stack<int> st;
void add(int x, int y)
{
    edg[tot].nxt = head[x];
    edg[tot].to = y;
    head[x] = tot++;
}
void tarjan(int u)
{
    st.push(u);
    low[u] = dfn[u] = ++cnt;
    for (int i = head[u]; ~i; i = edg[i].nxt)
    {
        int v = edg[i].to;
        if (!dfn[v])
        {
            tarjan(v);
            low[u] = min(low[u], low[v]);
        }
        else if (!scc[v])
            low[u] = min(low[u], dfn[v]);
    }
    if (low[u] == dfn[u])
    {
        ++scc_num;
        while (!st.empty())
        {
            int temp = st.top();
            st.pop();
            scc[temp] = scc_num;
            if (temp == u)
                break;
        }
    }
}
int main(int argc, char const *argv[])
{
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#endif
    int t = read<int>();
    while (t--)
    {
        n = read<int>(), m = read<int>();
        scc_num = 0, tot = 0;
        memset(head, -1, sizeof(int) * (n + 1));
        memset(scc, 0, sizeof(int) * (n + 1));
        memset(low, 0, sizeof(int) * (n + 1));
        memset(dfn, 0, sizeof(int) * (n + 1));
        memset(vis, 0, sizeof(int) * (n + 1));
        for (int i = 0; i < m; i++)
        {
            int x = read<int>(), y = read<int>();
            if (x == y)
                continue;
            add(x, y);
        }
        for (int i = 1; i <= n; i++)
            if (!dfn[i])
                tarjan(i);
        int pos = 0;
        for (int u = 1; u <= n; u++)
            for (int j = head[u]; ~j; j = edg[j].nxt)
            {
                int v = edg[j].to;
                if (scc[u] != scc[v])
                    vis[scc[u]] = 1;
            }
        for (int i = 1; i <= scc_num; i++)
            if (!vis[i])
            {
                pos = i;
                break;
            }
        if (!pos || scc_num == 1)
        {
            puts("No");
            continue;
        }
        int cnt = 0;
        for (int i = 1; i <= n; i++)
            if (scc[i] == pos)
                ++cnt;
        puts("Yes");
        printf("%d %d
", cnt, n - cnt);
        for (int i = 1; i <= n; i++)
            if (scc[i] == pos)
                printf("%d ", i);
        puts("");
        for (int i = 1; i <= n; i++)
            if (scc[i] != pos)
                printf("%d ", i);
        puts("");
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/mooleetzi/p/11718546.html