比赛杂题选讲「2022.10.22 ~ 今」

草,因为好多题都改不出来所以没脸写整场比赛的题解(

CSP-S模拟21

Once Again

ICEY 大佬友情供题。

一种比较显然的贪心策略是,找到出现次数最多的那个数,然后在中间重复的串里取他。

这个贪心确实是对的,然后两端特殊处理一下,满足一个单调不降即可。

code
#include <iostream>
#define GMY (520&1314)
#define char_phi int
#define re register int
#define FBI_OPENTHEDOOR(x, y) freopen(#x ".in", "r", stdin), freopen(#y ".out", "w", stdout);
#define Endl cout << '\n'
#define _ ' '
#define Dl cerr << '\n'
#define DMARK cerr << "###"
#define N 105
using namespace std;
inline void Fastio_setup(){ ios::sync_with_stdio(false); cin.tie(NULL), cout.tie(NULL); }
inline int MIN(int x, int y){ return ((x < y) ? (x) : (y)); }
inline int MAX(int x, int y){ return ((x > y) ? (x) : (y)); }

/*
	
*/

int n, T, m, final_ans, tmpans1, tmpans2;
int a[N*N], f[N*N], t[305];

inline void work(){
	cin >> n >> T; m = n * MIN(n, T);
	for (re i = 1 ; i <= n ; ++ i)
		{cin >> a[i]; t[a[i]] ++;}
	
	for (re i = n+1 ; i <= m ; ++ i)
		a[i] = a[i-n];
	
	for (re i = 1 ; i <= m ; ++ i){// 简单dp
		f[i] = 1;
		for (re j = i-1 ; j >= MAX(i-n, 1) ; -- j)
			if (a[i] >= a[j])
				f[i] = MAX(f[i], f[j]+1);
		tmpans1 = MAX(tmpans1, f[i]);
	}
	
	if (n >= T)
		{final_ans = tmpans1; goto OUT;}
	
	for (re i = 0 ; i <= 300 ; ++ i)
		tmpans2 = MAX(tmpans2, t[i]);
	final_ans = tmpans1 + tmpans2*(T-n);
	
	OUT:{cout << final_ans << '\n';}
}

#undef int
#define IXINGMY
char_phi main(){
	#ifdef IXINGMY
		FBI_OPENTHEDOOR(once, once);
	#endif
	Fastio_setup();
	work();
	return GMY;
}

考前欢乐赛

赛时以为这玩意是个反悔贪心

然后结束前十分钟发觉可以写个假做法上去,没准能骗到分

结果我写的那玩意就是正解(

因为有一个 sb 错误然后赛后很简单就 A

具体地,在一个 Ai 下降的阶段中,通过手模发现如果是交替着汇成人民币再汇成比特币再汇成人民币啥的,较直接在峰处换成比特币,在谷处换成人民币而言,后者更优。

于是大胆猜想贪心策略:峰处换比特币,谷处换人民币。

然后恭喜您这题就切了(

code
#include <iostream>
#include <cstdio>
#define GMY (520&1314)
#define char_phi signed
#define re register int
#define FBI_OPENTHEDOOR(x, y) freopen(#x ".in", "r", stdin), freopen(#y ".out", "w", stdout)
#define Endl cout << '\n'
#define _ ' '
#define Dl cerr << '\n'
#define DMARK cerr << "###"
#define N 200005
using namespace std;
inline void Fastio_setup() { ios :: sync_with_stdio(false); cin.tie(NULL), cout.tie(NULL); }
inline int MAX(int x, int y) { return ((x > y) ? (x) : (y)); }
inline int MIN(int x, int y) { return ((x < y) ? (x) : (y)); }

/*
    反悔贪心板子?
    但是为什么要输出路径
    理解不我
    哎板子我都不会
    等等,我有一个大胆的想法
*/

int n;
int a[N], ans[N];

inline void work() {
    cin >> n;
    for (re i = 1 ; i <= n ; ++ i)
        cin >> a[i];
    
    for (re i = 1, j ; i <= n-1 ; ++ i) {
        if (a[i] > a[i+1]) {
            j = i+1;
            while (a[j] > a[j+1] and j <= n-1)
                j ++;
            ans[i] = ans[j] = 1;
            i = j;
        }
    }
    
    for (re i = 1 ; i <= n ; ++ i)
        cout << ans[i] << _;
    Endl;
}

#undef int
#define IXINGMY
char_phi main() {
    #ifdef IXINGMY
        FBI_OPENTHEDOOR(coin, coin);
    #endif
    Fastio_setup();
    work();
    return GMY;
}

2022NOIP A层联测20

上来看到给定了 x+yxy 就立马激动了,哈哈哈韦达定理!!!

事实是伪了。

首先根据韦达定理显然可以很简单地得到 baca,钦定 a=1,那么根据二元一次方程求根公式可以确定两个解,再快速幂一下就行了。

我不知道这个钦定对不对啊,反正第一个样例带进去之后是对的(

就算这玩意是对的,取模意义下也会炸。注意到 xmodPxmodP,而给定的 x+yxy 都是取过模的,于是炸掉

解决方法好像用二次剩余什么玩意的,我不会,我讲递推做法。

首先明确我们要递推。设 fn=xn+yn,再设一个 fn=kfn1,那么也就是 xn+yn=kxn1+kyn1

显然 k 应该又有 x 又有 y,把 x+y 带进去试试:xn+xn1y+xyn1+yn,那我们要把 xn1y+xyn1 给容斥掉。

提出一个 xy 来,那么 xn1y+xyn1 就是 xy(xn2+yn2),这不就是 fn2 吗。于是递推柿就出来了:

fn=(x+y)fn1+xyfn2

于是快乐发现可以矩阵快速幂了。今天也终于懂了早就该懂的矩阵乘(

code
#include <iostream>
#include <cstdio>
#include <cstring>
#define GMY (520&1314)
#define char_phi int
#define re register int
#define FBI_OPENTHEDOOR(x, y) freopen(#x ".in", "r", stdin), freopen(#y ".out", "w", stdout)
#define Endl cout << '\n'
#define _ ' '
#define Dl cerr << '\n'
#define DMARK cerr << "###"
#define P 998244353
#define mod %
using namespace std;
inline void Fastio_setup() { ios::sync_with_stdio(false); cin.tie(NULL), cout.tie(NULL); }
inline int MAX(int x, int y) { return ((x > y) ? (x) : (y)); }
inline int MIN(int x, int y) { return ((x < y) ? (x) : (y)); }

/*
    我懂了!!!
    于是今天我学会了矩阵乘
    C矩阵的行是A矩阵的行,C矩阵的列是B矩阵的列
    根据递推柿可以得到基础矩阵
    然后矩阵乘结合律给结合一下就可以直接对基础矩阵进行快速幂了
    真有意思
*/

long long xjy, xy, n;

struct Matrix {
    long long f[3][3];
    
    inline void Clear() { memset(f, 0, sizeof(f)); }
    friend Matrix operator * (Matrix A, Matrix B) {// 基础矩阵的快速幂
        Matrix C; C.Clear();
        for (re i = 1 ; i <= 2 ; ++ i)// A矩阵第i行;
            for (re j = 1 ; j <= 2 ; ++ j)// B矩阵第j列;
                for (re k = 1 ; k <= 2 ; ++ k)// 共同的第k项;
                    C.f[i][j] = (C.f[i][j] + A.f[i][k] * B.f[k][j] mod P) mod P;// 我们是同志了。
        return C;
    }
};

struct Matrix ans;
struct Matrix basic;

inline Matrix Mksm(Matrix A, long long B) {
    struct Matrix res; res.Clear();// res是基础矩阵或者单位矩阵(一个东西乘上他还是那个东西)或者直接答案矩阵
    // res.f[1][1] = 1, res.f[2][2] = 1;// 是这样?
    res = A;
    while (B != 0) {
        if ((B & 1) == 1) res = res * A;
        A = A * A;
        B >>= 1;
    }
    return res;
}

inline void work() {
    cin >> xjy >> xy >> n;
    basic.f[1][1] = xjy, basic.f[1][2] = 1, basic.f[2][1] = -xy+P, basic.f[2][2] = 0;// 刚推出来的,不知道正确性
    ans.f[1][1] = xjy, ans.f[1][2] = 2;
    ans = ans * Mksm(basic, n-2);
    // Mksm(basic, n-1);
    cout << ans.f[1][1] << '\n';
}

#undef int
#define IXINGMY
char_phi main() {
    #ifdef IXINGMY
        FBI_OPENTHEDOOR(poly, poly);
    #endif
    Fastio_setup();
    work();
    return GMY;
}

这个题好像元素周期表啊。

赛时发现了,但是我真 sb 没去想最小生成树。

套路把每个点 xy 连边,每条边就代表一个点,边权就是那个点的点权。于是发现答案就是把整张图联通起来的最小代价。然后就做完了。具体为什么整张图联通就是全部都能买,可以参考我写的题解

暴力建边跑最小生成树即可,最小生成树就是把整张图联通起来的最小代价啊。。

因为是稠密图所以推荐跑 prim,但是我懒得建边其实是不会prim就跑了 Kruskal。跑 Kruskal 要注意常数,比如加个桶排之类的,卡卡就过了。

code
#include <iostream>
#include <cstdio>
#include <vector>
#include <ctime>
#define GMY (520&1314)
#define char_phi int
#define re register int
#define FBI_OPENTHEDOOR(x, y) freopen(#x ".in", "r", stdin), freopen(#y ".out", "w", stdout)
#define Endl cout << '\n'
#define _ ' '
#define Dl cerr << '\n'
#define DMARK cerr << "###"
#define N 5005
#define mod %
using namespace std;
inline void Fastio_setup() { ios::sync_with_stdio(false); cin.tie(NULL), cout.tie(NULL); }
inline int MAX(int x, int y) { return ((x > y) ? (x) : (y)); }
inline int MIN(int x, int y) { return ((x < y) ? (x) : (y)); }

/*
    简单至极
    我真是shab想到二分图没想最小生成树
    因为是个稠密图,需要卡常才能过?
    值域比较小,桶排!
*/

int n, m, P;
int final_ans;
long long tim;
int Fa[N<<1];

struct Tong {int u, v;};

vector<Tong> t[100005];

inline void GetInput() {
    cin >> n >> m; long long aa, bb, cc, dd, pp, Ai, Aii; cin >> aa >> bb >> cc >> dd >> pp; P = pp;
    Ai = aa;
    // for (re i = 0 ; i <= n*m-1 ; ++ i)
    // Dl;
    
    /*for (re i = 0 ; i <= n*m ; ++ i)
        cerr << A[i] << _;
    Dl;*/
    
    for (re i = 1, acnt(0) ; i <= n ; ++ i)
        for (re j = 1 ; j <= m ; ++ j) {
            Aii = (Ai * bb * Ai + Ai * cc + dd) mod pp;// cerr << A[i] << _;
            t[Aii].emplace_back((Tong){i, n+j});
            acnt ++; Ai = Aii;
        }
    cerr << (clock()-tim) * 1000 / CLOCKS_PER_SEC << '\n';
            // t[A[acnt]][++ t[A[acnt]][0].cnt] = (Tong){t[A[acnt]][0].cnt, i, n+j}, acnt ++;// cerr << A[acnt] << _ << i << _ << j << '\n';
}
inline void Prework() {
    GetInput();
    for (re i = 1 ; i <= n+m ; ++ i)
        Fa[i] = i;
}
int find(int x) { return ((Fa[x] == x) ? (x) : (Fa[x] = find(Fa[x]))); }
inline void Kruskal() {
    int chscnt = 0;
    for (re i = 0, fu, fv ; i <= P-1 ; ++ i)
        while (t[i].empty() == false) {
            // cerr << i << _ << t[i][t[i][0].cnt].u << _ << t[i][t[i][0].cnt].v-n << _ << _ << chscnt << '\n';
            fu = find((t[i].back()).u), fv = find((t[i].back()).v); t[i].pop_back();
            if (fu == fv)
                continue;
            chscnt ++; Fa[fu] = fv; final_ans += i;
            /*for (re i = 1 ; i <= n+m ; ++ i)
                cerr << Fa[i] << _;
            Dl;*/
            if (chscnt == n+m-1)
                return ;
        }
}

inline void work() {
    Prework();
    Kruskal();
    cout << final_ans << '\n';
}

#undef int
#define IXINGMY
char_phi main() {
    tim = clock();
    #ifdef IXINGMY
        FBI_OPENTHEDOOR(color, color);
    #endif
    Fastio_setup();
    work();
    return GMY;
}
posted @   char_phi  阅读(23)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示