Codeforces Round #663 (Div. 2) A-D

A : S u b o r r a y s A: Suborrays A:Suborrays
思路:
x ∣ y > = m a x ( x , y ) x|y>=max(x,y) xy>=max(x,y),线性输出即可。

参考代码:

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <ctime>
#include <cstring>
#include <cstdlib>
#include <math.h>
using namespace std;
typedef long long ll;
//#define ll long long
const int N = 2009;
const ll maxn = 1e5 + 20;
const ll mod = 1000000007;
int inv[maxn], vis[maxn], dis[maxn];
int fac[maxn], a[maxn], q[maxn], b[N], c[N];
vector<ll> vec;
//typedef pair<ll, ll> p;
//priority_queue<p, vector<p>, greater<p> > m;
// ll sum[maxn], a[maxn];
ll max(ll a, ll b) { return a > b ? a : b; }
ll min(ll a, ll b) { return a < b ? a : b; }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
ll lcm(ll a, ll b) { return a * b / gcd(a, b); }
map<ll, ll> mp;
ll ksm(ll a, ll b)
{
    a %= mod;
    ll ans = 1ll;
    while (b)
    {
        if (b & 1)
            ans = (ans * a) % mod;
        a = (a * a) % mod;
        b >>= 1ll;
    }
    return ans;
}
int dp[N][N];
char s[N][N];
// string p = "abacaba";
// queue<ll> qk, q;
//vector<ll> vec;
// ll sumx[maxn], sumy[maxn], sumk[maxn];
int cnt;
map<int, int> p;
struct node
{
    int ls, rs, sum;
} tr[maxn * 32];
void inser(int &k, int L, int R, int pos, int w)
{
    if (!k)
        k = ++cnt;
    tr[k].sum += w;
    if (L == R)
        return;
    int mid = L + R >> 1;
    if (mid >= pos)
        inser(tr[k].ls, L, mid, pos, w);
    else
        inser(tr[k].rs, mid + 1, R, pos, w);
}
int query(int k, int L, int R, int ik)
{
    if (L == R)
        return L;
    int sk = tr[tr[k].ls].sum;
    int mid = L + R >> 1;
    if (sk >= ik)
        return query(tr[k].ls, L, mid, ik);
    else
        return query(tr[k].rs, mid + 1, R, ik - sk);
}
int lx[N][N], rx[N][N], bl[N][N], br[N][N], wup[N][N], down[N][N];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    //ll t, n, ans;
    // scanf("%lld", &t);
    int t, n;
    cin >> t;
    while (t--)
    {
        cin >> n;
        for (int i = 1; i <= n; i++)
            cout << i << ' ';
        cout << endl;
    }
}

B − F i x Y o u B - Fix You BFixYou

思路:
由于只能往下走或往右走,所以我们只考虑,最下一行的能否到达,和最右一列的能否到达即可,因为其他的点必然会经过最后一行或者最右一列。

参考代码:

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <ctime>
#include <cstring>
#include <cstdlib>
#include <math.h>
using namespace std;
typedef long long ll;
//#define ll long long
const int N = 2009;
const ll maxn = 1e5 + 20;
const ll mod = 1000000007;
int inv[maxn], vis[maxn], dis[maxn];
int fac[maxn], a[maxn], q[maxn], b[N], c[N];
vector<ll> vec;
//typedef pair<ll, ll> p;
//priority_queue<p, vector<p>, greater<p> > m;
// ll sum[maxn], a[maxn];
ll max(ll a, ll b) { return a > b ? a : b; }
ll min(ll a, ll b) { return a < b ? a : b; }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
ll lcm(ll a, ll b) { return a * b / gcd(a, b); }
map<ll, ll> mp;
ll ksm(ll a, ll b)
{
    a %= mod;
    ll ans = 1ll;
    while (b)
    {
        if (b & 1)
            ans = (ans * a) % mod;
        a = (a * a) % mod;
        b >>= 1ll;
    }
    return ans;
}
int dp[N][N];
char s[N][N];
// string p = "abacaba";
// queue<ll> qk, q;
//vector<ll> vec;
// ll sumx[maxn], sumy[maxn], sumk[maxn];
int cnt;
map<int, int> p;
struct node
{
    int ls, rs, sum;
} tr[maxn * 32];
void inser(int &k, int L, int R, int pos, int w)
{
    if (!k)
        k = ++cnt;
    tr[k].sum += w;
    if (L == R)
        return;
    int mid = L + R >> 1;
    if (mid >= pos)
        inser(tr[k].ls, L, mid, pos, w);
    else
        inser(tr[k].rs, mid + 1, R, pos, w);
}
int query(int k, int L, int R, int ik)
{
    if (L == R)
        return L;
    int sk = tr[tr[k].ls].sum;
    int mid = L + R >> 1;
    if (sk >= ik)
        return query(tr[k].ls, L, mid, ik);
    else
        return query(tr[k].rs, mid + 1, R, ik - sk);
}
int lx[N][N], rx[N][N], bl[N][N], br[N][N], wup[N][N], down[N][N];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    //ll t, n, ans;
    // scanf("%lld", &t);
    int t, n, m;
    cin >> t;
    while (t--)
    {
        cin >> n >> m;
        for (int i = 1; i <= n; i++)
            cin >> (s[i] + 1);
        int ans = 0;
        for (int i = 1; i < m; i++)
        {
            if (s[n][i] != 'R')
                ans++;
        }
        for (int i = 1; i < n; i++)
        {
            if (s[i][m] != 'D')
                ans++;
        }
        cout << ans << endl;
    }
}

C : C y c l i c P e r m u t a t i o n s C:Cyclic Permutations CCyclicPermutations
思路:
没啥思路这个,我题其实没怎么看懂,但是几分钟就A了,因为能看出这个是个规律题,那么对于规律题,一般都是阶乘, 2 n 2^n 2n n k n^k nk之类的,我随意构造了几个,发现第一个过了,第二个也过了,就A了 。

参考代码:

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <ctime>
#include <cstring>
#include <cstdlib>
#include <math.h>
using namespace std;
typedef long long ll;
//#define ll long long
const int N = 2009;
const ll maxn = 1e5 + 20;
const ll mod = 1000000007;
int inv[maxn], vis[maxn], dis[maxn];
int fac[maxn], a[maxn], q[maxn], b[N], c[N];
vector<ll> vec;
//typedef pair<ll, ll> p;
//priority_queue<p, vector<p>, greater<p> > m;
// ll sum[maxn], a[maxn];
ll max(ll a, ll b) { return a > b ? a : b; }
ll min(ll a, ll b) { return a < b ? a : b; }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
ll lcm(ll a, ll b) { return a * b / gcd(a, b); }
map<ll, ll> mp;
ll ksm(ll a, ll b)
{
    a %= mod;
    ll ans = 1ll;
    while (b)
    {
        if (b & 1)
            ans = (ans * a) % mod;
        a = (a * a) % mod;
        b >>= 1ll;
    }
    return ans;
}
ll dp[1000005];
char s[N][N];
// string p = "abacaba";
// queue<ll> qk, q;
//vector<ll> vec;
// ll sumx[maxn], sumy[maxn], sumk[maxn];
int cnt;
map<int, int> p;
struct node
{
    int ls, rs, sum;
} tr[maxn * 32];
void inser(int &k, int L, int R, int pos, int w)
{
    if (!k)
        k = ++cnt;
    tr[k].sum += w;
    if (L == R)
        return;
    int mid = L + R >> 1;
    if (mid >= pos)
        inser(tr[k].ls, L, mid, pos, w);
    else
        inser(tr[k].rs, mid + 1, R, pos, w);
}
ll f()
{
    dp[0] = 1;
    for (ll i = 1; i <= 1000005; i++)
        dp[i] = dp[i - 1] * i % mod;
}
int query(int k, int L, int R, int ik)
{
    if (L == R)
        return L;
    int sk = tr[tr[k].ls].sum;
    int mid = L + R >> 1;
    if (sk >= ik)
        return query(tr[k].ls, L, mid, ik);
    else
        return query(tr[k].rs, mid + 1, R, ik - sk);
}
int lx[N][N], rx[N][N], bl[N][N], br[N][N], wup[N][N], down[N][N];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    //cout << (583291ll * 583291ll % mod) << endl;
    //ll t, n, ans;
    // scanf("%lld", &t);
    ll t, n, m;
    // cin >> t;
    f();
    // while (t--)
    // {
    cin >> n;
    cout << ((dp[n] - ksm(2, n - 1) + mod) % mod) << endl;
    // }
}

D − 505 D - 505 D505

思路:枚举子集+贪心
可以确定的是当 n > 3 n>3 n>3时无解,因为由于 m > = n m>=n m>=n,所以当 n > 3 n>3 n>3 n , m n,m n,m组成的大矩阵中一定含 4 ∗ 4 4*4 44的小矩阵,证明 4 ∗ 4 4*4 44的矩阵无解如下图:
在这里插入图片描述
所以现在我们可以确定 n n n的范围属于 [ 1 , 3 ] [1,3] [1,3],显然这么小的数据范围是可以枚举的,所以我们枚举第一列的状态,的到该状态的01序列,通过第一列的状态构造符合条件的矩阵,在构造中获得每一种状态修改的次数,枚举最小值。
n = 1 n=1 n=1,答案直接输出 0 0 0即可, n > 3 n>3 n>3输出 − 1 -1 1 n = 2 ∣ ∣ n = 3 n=2||n=3 n=2n=3,构造合法答案,显然我们已知第一列的状态,第二列的状态可由给定矩阵构造出,直至构造到第 m m m列,具体操作看一下代码。

参考代码:

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <ctime>
#include <cstring>
#include <cstdlib>
#include <math.h>
using namespace std;
typedef long long ll;
//#define ll long long
const int N = 2009;
const ll maxn = 1e5 + 20;
const ll mod = 1000000007;
int inv[maxn], vis[maxn], dis[maxn];
int fac[maxn], a[maxn], q[maxn], b[N], c[N];
vector<ll> vec;
//typedef pair<ll, ll> p;
//priority_queue<p, vector<p>, greater<p> > m;
// ll sum[maxn], a[maxn];
ll max(ll a, ll b) { return a > b ? a : b; }
ll min(ll a, ll b) { return a < b ? a : b; }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
ll lcm(ll a, ll b) { return a * b / gcd(a, b); }
map<ll, ll> mp;
ll ksm(ll a, ll b)
{
    a %= mod;
    ll ans = 1ll;
    while (b)
    {
        if (b & 1)
            ans = (ans * a) % mod;
        a = (a * a) % mod;
        b >>= 1ll;
    }
    return ans;
}
// ll dp[1000005];
// char s[N][N];
// // string p = "abacaba";
// // queue<ll> qk, q;
// //vector<ll> vec;
// // ll sumx[maxn], sumy[maxn], sumk[maxn];
// int cnt;
// map<int, int> p;
int dp[3][1000005];
string matrix[1000005];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int t, n, m;
    // cin >> t;
    //f();
    // while (t--)
    // {
    cin >> n >> m;
    for (int i = 0; i < n; i++)
        cin >> matrix[i];
    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
            matrix[i][j] -= '0';
    if (n == 1)
        cout << 0 << endl;
    else if (n >= 4)
        cout << -1 << endl;
    else
    {
        int ans = 999999999;
        for (int i = 0; i < (1 << n); i++)
        {
            int cur = 0;
            for (int j = 0; j < n; j++)
            {
                dp[j][0] = (i >> j) & 1;
                if (matrix[j][0] != dp[j][0])
                    cur++;
            }
            for (int j = 1; j < m; j++)
            {
                dp[0][j] = matrix[0][j];
                dp[1][j] = matrix[1][j];
                dp[2][j] = matrix[2][j];
                int res1 = dp[0][j] + dp[1][j] + dp[0][j - 1] + dp[1][j - 1];
                if (n == 3)
                {
                    int res2 = dp[1][j] + dp[2][j] + dp[1][j - 1] + dp[2][j - 1];
                    if ((res1 & 1) && (res2 & 1))
                        continue;
                    if (res1 & 1)
                        dp[2][j] ^= 1, cur++;
                    else if (res2 & 1)
                        dp[0][j] ^= 1, cur++;
                    else
                        dp[1][j] ^= 1, cur++;
                }
                else
                {
                    if (!(res1 & 1))
                        dp[0][j] ^= 1, cur++;
                }
            }
            ans = min(cur, ans);
        }
        cout << ans << endl;
    }
    // }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值