看板娘加载较慢请耐心等待qwq~~~

2019.10.12模拟赛

关于这次考试

什么神仙题啊上来大模拟???

T1 德州扑克

就是给你七张牌输出权值最大的牌。
大模拟就好了,注意细节,注意读题。

#include <bits/stdc++.h>
using namespace std;
namespace tx {
const int COLOR_MAX = 14;
const int HAVE_MAX = 7;
const int MAXN = 10;
char color[20];
int a[MAXN];
int have[20];
int ans[MAXN], tot;
inline void in(const int &x) { ans[++tot] = x; }
inline void out() {
    assert(tot == 5);
    sort(ans + 1, ans + 5 + 1, greater<int>());
    for (register int i = 1; i <= 5; ++i) {
        if (ans[i] == 10)
            cout << 10 << " ";
        else
            cout << color[ans[i]] << " ";
    }
    return;
}
inline int main() {
    for (register int i = 1; i <= 9; ++i) color[i] = i + '0';
    color[11] = 'J';
    color[12] = 'Q';
    color[13] = 'K';
    color[14] = 'A';
    color[1] = 'A';
    for (register int i = 1; i <= HAVE_MAX; ++i) {
        char s[5];
        cin >> s;
        if (s[0] == 'A')
            a[i] = 14;
        else if (s[0] == 'K')
            a[i] = 13;
        else if (s[0] == 'Q')
            a[i] = 12;
        else if (s[0] == 'J')
            a[i] = 11;
        else if (s[0] == '1' && s[1] == '0')
            a[i] = 10;
        else
            a[i] = s[0] - '0';
        ++have[a[i]];
        if (a[i] == 14)
            ++have[1];
    }
    sort(a + 1, a + 1 + HAVE_MAX, greater<int>());
    // judge 1
    for (register int i = COLOR_MAX; i >= 2; --i) {
        if (have[i] >= 4) {
            for (register int j = 1; j <= 4; ++j) in(i);
            for (register int j = 1; j <= HAVE_MAX; ++j) {
                if (a[j] != i) {
                    in(a[j]);
                    break;
                }
            }
            out();
            return 1;
        }
    }
    // judge2
    register int bo3 = 0, bo2 = 0;
    for (register int i = COLOR_MAX; i >= 2; --i) {
        if (!bo3 && have[i] >= 3) {
            bo3 = i;
            continue;
        }
        if (!bo2 && have[i] >= 2) {
            bo2 = i;
            continue;
        }
    }
    if (bo3 && bo2) {
        for (register int i = 1; i <= 3; ++i) in(bo3);
        for (register int i = 1; i <= 2; ++i) in(bo2);
        out();
        return 2;
    }
    // judge3
    for (register int i = COLOR_MAX - 4; i >= 1; --i) {
        register bool bo = 1;
        for (register int j = 0; j <= 4; ++j) {
            if (!have[i + j]) {
                bo = 0;
                break;
            }
        }
        if (bo) {
            for (register int j = 0; j <= 4; ++j) {
                in(i + j);
            }
            out();
            return 3;
        }
    }
    // judge4
    bo3 = bo2 = 0;
    for (register int i = COLOR_MAX; i >= 2; --i) {
        if (have[i] >= 3) {
            bo3 = i;
            break;
        }
    }
    if (bo3) {
        for (register int i = 1; i <= 3; ++i) {
            in(bo3);
        }
        register int cnt = 0;
        for (register int j = 1; j <= HAVE_MAX; ++j) {
            if (a[j] != bo3) {
                in(a[j]);
                ++cnt;
            }
            if (cnt >= 2)
                break;
        }
        out();
        return 4;
    }
    // judge5
    bo3 = 0, bo2 = 0;
    for (register int i = COLOR_MAX; i >= 2; --i) {
        if (!bo3 && have[i] >= 2) {
            bo3 = i;
            continue;
        }
        if (!bo2 && have[i] >= 2) {
            bo2 = i;
            break;
        }
    }
    if (bo3 && bo2) {
        in(bo3), in(bo3);
        in(bo2), in(bo2);
        for (register int i = 1; i <= HAVE_MAX; ++i) {
            if (a[i] != bo3 && a[i] != bo2) {
                in(a[i]);
                break;
            }
        }
        out();
        return 5;
    }
    // judge6
    bo3 = bo2 = 0;
    for (register int i = COLOR_MAX; i >= 2; --i) {
        if (have[i] >= 2) {
            bo3 = i;
            break;
        }
    }
    if (bo3) {
        in(bo3), in(bo3);
        register int cnt = 0;
        for (register int i = 1; i <= HAVE_MAX; ++i) {
            if (a[i] != bo3) {
                in(a[i]);
                ++cnt;
            }
            if (cnt >= 3)
                break;
        }
        out();
        return 6;
    }
    // judge7
    for (register int i = 1; i <= 5; ++i) in(a[i]);
    out();
    return 7;
    return 0;
}
}  // namespace tx
int main() {
#ifdef lky233
    freopen("texas.in", "r", stdin);
    freopen("texas.out", "w", stdout);
#endif
    tx::main();
}

这道题由于情况很多,人工模拟又很容易出锅……hack起来很爽快
至于maker,因为这道题的状态是有限的,可以枚举状态,maker就可以先读入seed来获知当前状态,接着求出下一个合法状态并更新seed。
这样的maker有几个好处:
不是rand而是枚举状态,不会遗漏。
可以手动更改seed以构造特殊数据。
但也有坏处:
枚举全部状态时间过长。
有很多相似的状态不会拍出错误,效率降低。
(找一个机房空机子挂上两天也是可以的)

#include <bits/stdc++.h>
using namespace std;
char color[100];
int seed[100];
int v[20];
inline void nex()
{
	++seed[7];
	for (register int i = 7; i >= 1; --i)
	{
		if (seed[i] > 13)
		{
			seed[i] = 1;
			++seed[i - 1];
		}
	}
	if(seed[1] == 14)
	{
		while(1)
			;
		cerr << "accept" << endl;
	}
}
inline bool judge()
{
	memset(v, 0, sizeof(v));
	for (register int i = 1; i <= 7; ++i)
	{
		++v[seed[i]];
		if (v[seed[i]] > 4)
			return false;
	}
	return true;
}
int main()
{
	freopen("seed.txt", "r", stdin);
	// freopen("seed.txt", "w", stdout);
	for (register int i = 1; i <= 9; ++i)
		color[i] = i + '0';
	color[11] = 'J';
	color[12] = 'Q';
	color[13] = 'K';
	color[14] = 'A';
	color[1] = 'A';
	for (register int i = 1; i <= 7; ++i)
		scanf("%d", &seed[i]);
	nex();
	while (!judge())
		nex();
	freopen("seed.txt", "w", stdout);
	for (register int i = 1; i <= 7; ++i)
		printf("%d ", seed[i]);
	freopen("texas.in", "w", stdout);
	for (register int i = 1; i <= 7; ++i)
	{
		if (seed[i] == 10)
			printf("10\n"), cerr << 10 << " ";
		else
			printf("%c\n", color[seed[i]]), cerr << color[seed[i]] << " ";
	}
	cerr << endl;
}

T2 战斗

题面

秦师兄手下有𝑛个士兵,每个士兵有一个战斗力𝑎𝑖。他打算从中挑选出至少𝑘个士兵组成一
支部队,并在选出的士兵中挑选出一个作为队长。然而秦师兄并不关心部队的战斗力。他只希
望部队的混乱度最小。混乱度的定义为:所有士兵的战斗力与队长的战斗力之差的平方和。秦
师兄想知道最小的混乱度是多少。
第二行𝑛个不严格递增的正整数𝑎𝑖,表示𝑛个士兵的战斗力。

做法

首先\(\geq k\)个数可以转化为\(k\)个数,因为多一个数会导致值只增不减。并且取值是连续的,因为若取不连续的一段,一定有未取到的数使得答案更优。
其次,一段序列与x的差的平方和最小,x是平均数。

证明:
$ans = \sum\limits_{i = 1}^{i \leq len}(a_i - x)^2 $$= \sum\limits_{i = 1}^{i \leq len}a_{i}^2 - \sum\limits_{i = 1}^{i \leq len} {2 \cdot a_i \cdot x} + len \cdot x^2$
我们发现这是个二次函数,找到最小值:
\(x = \frac{\sum\limits_{i = 1}^{i \leq len} a_i}{len} = \bar a\)

这样我们可以二分查找区间内最接近\(\bar a\)的数,O(1)计算该区间的值。时间复杂度\(O(n \log n)\)

    poread(n), poread(k);
    for (register int i = 1; i <= n; ++i) poread(a[i]);
    for (register int i = 1; i <= n; ++i) q[i] = (long long)a[i] * a[i];
    for (register int i = 1; i <= n; ++i) sum[i] = sum[i - 1] + a[i];
    for (register int i = 1; i <= n; ++i) sum_q[i] = sum_q[i - 1] + q[i];
    for (l = 1; (r = l + k - 1) <= n; ++l) {
        register long long mid = (sum[r] - sum[l - 1]) / (r - l + 1);
        int mid1 = find1(mid), mid2 = find2(mid);
        if (mid1 == mid2) {
            ans = min(ans, calc(a[mid1]));
        } else {
            ans = min(ans, calc(a[mid1]));
            ans = min(ans, calc(a[mid2]));
        }
    }
    printf("%lld\n", ans);

但序列递增,所以决策点只会右移。所以可以\(O(n)\)扫描一遍得到答案。

    int main() {
    poread(n), poread(k);
    for (register int i = 1; i <= n; ++i) poread(a[i]);
    for (register int i = 1; i <= n; ++i) sum[i] = sum[i - 1] + a[i];
    for (register int i = 1; i <= n; ++i) sum_q[i] = sum_q[i - 1] + 1ll * a[i] * a[i];
    long long mid = sum[k] / k;
    register int point = find1(mid);
    register long long tmp;
    for (l = 1; (r = l + k - 1) <= n; ++l) {
        while (calc(a[point + 1]) <= (tmp = calc(a[point]))) ++point;
        ans = min(ans, tmp);
    }
    printf("%lld\n", ans);
}

T3 计数

题面

别看秦师兄平时一副热爱打游戏的样子,但在信息学计数题上的造诣可谓是颇深,你看在这 次模拟赛中,他就除了这样一道计数题。
秦师兄觉得图论很有趣。因此有一个𝑛个点的有向图,编号从 1 到𝑛,所有边的长度都是 1。
秦师兄还想融合一些数论元素。因此 i 向 j 连边当且仅当 i 整除 j。请注意一个正整数必定
整除它自身,因而秦师兄允许了自环的存在。
秦师兄觉得还不够好,因为所有的正整数都整除 0。于是她新建了一个编号为 0 的点,并
让 1−𝑛 的所有点都向 0 连一条长度为 1 的边。
秦师兄现在很满意。她写下了下面 4 个问题交给你来解决。

  1. 求出从 1 到𝑞1,且长度恰为 2 的路径个数。
  2. 求出从 1 到 0,且长度不大于𝑞2的路径个数。
  3. 求出从 1 到 0,没有经过重复的点,且长度不大于𝑞3的路径个数。
  4. 令一条路径的权值为它经过的所有的点的编号之和。求出 (问题 3.)中所有路径的权值
    和。
    所有问题的答案对 109 + 7 取模。秦师兄不希望你爆零,因此设置了部分分。请注意最后的部分分设定
    lemon没有部分分啊
int main()
{
	cin >> n >> q1 >> q2 >> q3;
	register int i = 1;
	for (i = 1; i * i <= q1; ++i)
		if (q1 % i == 0)
			ans1 += 2;
	--i;
	if (i * i == q1)
		--ans1;
	if (q1 == 0)
		ans1 = n;
	int t = log2(n) + 1;
	for (register int l = 1, d, r; l <= n; l = r + 1)
		id[d = n / l] = ++tot, pos[tot] = d, r = n / d;
	for (register int i = 1; i <= tot; ++i)
		f[i][1] = g[i][1] = 1;
	for (register int j = 1; j < t; ++j)
	{
		for (register int i = 1; i <= tot; ++i)
		{
			register int x = pos[i];
			for (register int l = 2, d, r; l <= x; l = r + 1)
			{
				d = x / l, r = x / d;
				register int len = r - l + 1;
				f[i][j + 1] = (f[i][j + 1] + 1ll * len * f[id[d]][j] % MOD) % MOD;
				g[i][j + 1] = (g[i][j + 1] + 1ll * len * (l + r) / 2 % MOD * g[id[d]][j] % MOD + 1ll * len * f[id[d]][j] % MOD) % MOD;
			}
		}
	}
	for (register int i = 1; i <= min(q3, t); ++i)
		ans3 = (ans3 + f[1][i]) % MOD;
	for (register int i = 1; i <= min(q3, t); ++i)
		ans4 = (ans4 + g[1][i]) % MOD;
	inv[1] = c[0] = 1;
	for (register int i = 2; i <= t; ++i)
		inv[i] = 1ll * (MOD - MOD / i) % MOD * inv[MOD % i] % MOD;
	for (register int i = 1; i <= t; ++i)
		c[i] = 1ll * c[i - 1] * inv[i] % MOD * (q2 - i + 1) % MOD;
	for (register int i = 1; i <= t; ++i)
		ans2 = (ans2 + 1ll * c[i] * f[1][i]) % MOD;
	printf("%d %d %d %d", ans1, ans2, ans3, ans4);
	return 0;
}
posted @ 2019-10-17 14:07  椎名·六花  阅读(173)  评论(0编辑  收藏  举报