2019 牛客多校第二场 4/10

题会慢慢补完的,最近在帮别人上课,补题速度很慢,一边看ppt一边刷ppt的题还要补多校的,感觉有点应付不过来,不过以后会慢慢补完的(指整个暑假)

A

这场出题人的英文水平真的搞事,不说了(((
这题起码读了X遍才搞明白题意,每次读都是不同的意思,出题人好好表达不行吗(((
题意是说这个人在长度为N的环上走,等概率随机往左往右,如果全部走完一次就离开,问在M点离开的概率。
再次吐槽,这个N也真的搞事,有时用来表达N steps有时又是长度为N,而且输出还是前缀和
考虑吸收壁的随机游走,然后我们改一下,改成环,吸收条件也改一下,但是这依然可以感受出来极限情况下除了0不能作为结束之外等概率(严格证起来好像很日,然后就完了

/* ***********************************************
Author        :BPM136
Created Time  :7/21/2019 7:24:02 PM
File Name     :A.cpp
************************************************ */

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<iomanip>
#include<bitset>
#include<queue>
#include<ctime>
#include<set>
#include<map>
#include<list>
#include<vector>
#include<cassert>
#include<string>
#include<cinttypes>
#include<cstdint>
#include<array>
#define SZ(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define USE_CIN_COUT ios::sync_with_stdio(0)

using namespace std;

typedef long long ll;
typedef double db;
typedef long double ld;
typedef unsigned int ui;
typedef unsigned long long ull;

ll const mod = 1e9 + 7;

ll KSM(ll a, ll k) {
	ll ret = 1;
	for (; k; k >>= 1, a = a * a % mod)
		if (k & 1)
			ret = ret * a % mod;
	return ret;
}

int main() {
	USE_CIN_COUT;
	int T, n, m;
	cin >> T;
	ll ans = 1;
	for (int i = 1; i <= T; ++i) {
		cin >> n >> m;
		if (n != 1) {
			if (m == 0)
				ans = 0;
			else
				ans = ans * KSM(n - 1, mod - 2) % mod;
		}
		cout << ans << '\n';
	}
    return 0;
}

B

C

D

显然大团是包含小团的,不过比赛的时候上头了没考虑怎么优化,只想着卡常(((
其实只要把bfs的时候让1的赋予顺序是从左往右就行,这样就从 O ( K n l o g ( K n ) ) O(Knlog(Kn)) O(Knlog(Kn))变成了 O ( K l o g ( K n ) ) O(Klog(Kn)) O(Klog(Kn))
以及判断的时候可以压位,这样就 O ( N 64 ) O(\frac{N}{64}) O(64N)的判断时间了(就是这个给了我盲目的信心想大力爆过去((((

/* ***********************************************
Author        :BPM136
Created Time  :7/20/2019 1:35:41 PM
File Name     :D.cpp
************************************************ */
  
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<iomanip>
#include<bitset>
#include<queue>
#include<ctime>
#include<set>
#include<map>
#include<list>
#include<vector>
#include<cassert>
#include<string>
#include<cinttypes>
#include<cstdint>
#include<array>
#define SZ(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define USE_CIN_COUT ios::sync_with_stdio(0)
  
using namespace std;
  
typedef long long ll;
typedef double db;
typedef long double ld;
typedef unsigned int ui;
typedef unsigned long long ull;
  
int const N = 105;
  
string e[N];
ll e_st1[N], e_st2[N];
int a[N];
int n, K;
  
struct node {
    ll st1, st2;
    ll val;
    node() {}
    node(ll _st1, ll _st2, ll _val) : st1(_st1), st2(_st2), val(_val) {}
    bool operator<(node const& oth) const {
        return val > oth.val;
    }
};
  
inline void getSt(ll st1, ll st2, ll& nst1, ll& nst2, int np) {
    nst1 = st1;
    nst2 = st2;
    if (np < 50)
        nst1 |= 1LL << np;
    else
        nst2 |= 1LL << (np - 50);
}
  
inline node getNewNode(node const& x, int np) {
    node ret = x;
    if (np < 50)
        ret.st1 |= 1LL << np;
    else
        ret.st2 |= 1LL << (np - 50);
    ret.val += a[np];
    return ret;
}
  
inline bool pInSta(ll const& st1, ll const& st2, int p) {
    if (p < 50)
        return st1 & (1LL << p);
    else
        return st2 & (1LL << (p - 50));
}
  
inline bool eInSta(ll const& st1, ll const& st2, ll const& e1, ll const& e2) {
    return ((st1 & e1) == st1) && ((st2 & e2) == st2);
}
  
//set<node> S;
  
int main() {
	double tt = clock();
	freopen("in.txt", "r", stdin);
    cin >> n >> K;
    --K;
    for (int i = 0; i < n; ++i)
        cin >> a[i];
    for (int i = 0; i < n; ++i)
        cin >> e[i];
    for (int i = 0; i < n; ++i)
        for (int j = 0; j < n; ++j)
            if (e[i][j] == '1')
                getSt(e_st1[i], e_st2[i], e_st1[i], e_st2[i], j);
    //bitset<5> debug1, debug2;
    auto Q = priority_queue<node>();
    Q.push(node{ 0, 0, 0 });
    // S.insert(node{ 0, 0, 0 });
    node tmp;
    while (Q.empty() == 0 && K--) {
        auto now = Q.top();
        Q.pop();
        //debug1 = now.st1, debug2 = now.st2;
        // cerr << debug1 << ' ' << debug2 << ' ' << now.val << ' ' << Q.size() << ' ' << K << '\n';
        int mx = 0;
        for (int i = 0; i < n; ++i)
            if (pInSta(now.st1, now.st2, i))
                mx = i + 1;
        for (int i = mx; i < n; ++i)
            if (eInSta(now.st1, now.st2, e_st1[i], e_st2[i])) {
                tmp = getNewNode(now, i);
                //if (S.count(tmp) == 0) {
                    Q.push(tmp);
                //    S.insert(tmp);
                //}
            }
    }
    // cerr << K << ' ' << Q.empty() << ' ' << Q.top().val << '\n';
    if (K >= 0 || Q.empty())
        cout << -1 << '\n';
    else
        cout << Q.top().val << '\n';
	cerr << clock() - tt << '\n';
    return 0;
}

E

F

dfs

#include <iostream>
#include <limits>
#include <cstdint>
#include <algorithm>
#include <string>
#include <vector>
 
using i64 = int64_t;
const int N = 14 * 2;
 
int n, v[N][N];
int ss1[N], ss2[N];
i64 ans, cur;
 
void dfs (int i, int cnt1) {
    if (ans <= cur)
        return;
    if (i == n) {
        ans = cur;
        return;
    }
 
    if (cnt1 < (n >> 1)) {
        i64 s1 = 0;
        for (int j = 0; j < cnt1; ++j)
            s1 += v[i][ss1[j]];
        ss1[cnt1] = i;
        // std::cerr << "> " << i << " " << s1 << "\n";
        cur += s1;
        dfs(i + 1, cnt1 + 1);
        cur -= s1;
    }
 
    int cnt2 = i - cnt1;
    if (cnt2 < (n >> 1)) {
        i64 s2 = 0;
        for (int j = 0; j < cnt2; ++j)
            s2 += v[i][ss2[j]];
        ss2[cnt2] = i;
        cur += s2;
        dfs(i + 1, cnt1);
        cur -= s2;
    }
}
 
int main () {
    std::ios::sync_with_stdio(false);
 
    std::cin >> n;
    n *= 2;
 
    i64 sum = 0;
    for (int i = 0; i < n; ++i)
        for(int j = 0; j < n; ++j) {
            std::cin >> v[i][j];
            if (i < j)
                sum += v[i][j];
        }
 
    ans = std::numeric_limits<i64>::max();
    cur = 0;
    dfs(0, 0);
    // std::cerr << "s = " << ans << '\n';
    std::cout << sum - ans << '\n';
 
    return 0;
}

G

H

原题,单调栈爆过去就行

/* ***********************************************
Author        :BPM136
Created Time  :7/20/2019 12:41:43 PM
File Name     :H.cpp
************************************************ */

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<iomanip>
#include<bitset>
#include<queue>
#include<ctime>
#include<set>
#include<map>
#include<list>
#include<vector>
#include<cassert>
#include<string>
#include<cinttypes>
#include<cstdint>
#include<array>
#define SZ(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define USE_CIN_COUT ios::sync_with_stdio(0)

using namespace std;

typedef long long ll;
typedef double db;
typedef long double ld;
typedef unsigned int ui;
typedef unsigned long long ull;

int const N = 1005;

int lef[N], sta[N];
int row[N][N];
int val[N][N];
int a[N][N];
int n, m;

void update(int& ans1, int& ans2, int tmp) {
	if (tmp >= ans1) {
		ans2 = ans1;
		ans1 = tmp;
	} else
		if (tmp > ans2) 
			ans2 = tmp;
}
 
int main() {
	cin >> n >> m;
	string s;
	for (int i = 1; i <= n; ++i) {
		cin >> s;
		for (int j = 1; j <= m; ++j) {
			a[i][j] = s[j - 1] == '1';
			if (a[i][j]) 
				a[i][j] = a[i][j - 1] + 1;
		}
	}
	auto ans1 = 0, ans2 = 0;
	for (int j = 1; j <= m; ++j) {
		int top = 0;
		a[n + 1][j] = -1;
		for (int i = 1; i <= n + 1; ++i) {
			if (top == 0 || a[i][j] > a[sta[top - 1]][j]) {
				sta[top++] = i;
				lef[i] = i;
				continue;
			}
			if (a[i][j] == a[sta[top - 1]][j])
				continue;
			while (top >= 1 && a[i][j] < a[sta[top - 1]][j]) {
				--top;
				update(ans1, ans2, (i - lef[sta[top]]) * a[sta[top]][j]);
				update(ans1, ans2, (i - lef[sta[top]] - 1) * a[sta[top]][j]);
				update(ans1, ans2, (i - lef[sta[top]]) * (a[sta[top]][j] - 1));
			}
			lef[i] = lef[sta[top]];
			sta[top++] = i;
		}
	}
	cout << ans2 << endl;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值