首页 > 其他分享 >第二周训练总结

第二周训练总结

时间:2023-07-20 18:56:43浏览次数:40  
标签:总结 tmp num 训练 int long 第二周 maxn dp

第二周训练总结

比赛

第四场个人赛

AC:

  • A:水题,签到题
  • B:枚举,枚举每两个字符串,如果这两个串没有同一位都是 $x$,答案就加一
  • C:模拟,用一个 $flag$ 记录遍历到的引号是否为奇数下标,然后用.去替换,即可
  • I:分类讨论,分别判断字符串长度、首位字符、第二个字符以及其余字符即可
  • J:模拟,首先预处理一下输入的 $m$ ,减去 m/tot * tot,最后遍历一遍数组即可

补题:

D:
  • 题意:给你一个有$N$个顶点和$M$条边的简单无向图$G$,你可以连接任意原本没有边的点$u$、$v$,使得结果是一个二分图,打印有几种连接的方法。

  • 重点是将其转化为二分图模型,我们考虑三种情况:

    • 当前只有一个联通分量,且该联通分量内本身为一个二分图:
      此时我们只需要染色后得到c1,c2(将图内的点分为两部分),(c1*c2-m)就是答案,表示所有满足二分图的边除去已有的边。
    • 当前有多个联通分量,且各联通分量内部都为二分图:
      此时我们对其中一个联通分量染色后得到(res1 += (c1*c2))所有可能的边,(res2 += (c1+c2) * (n-(c1+c2)) )当前联通分量可以和其他联通分量之间内连多少条边
      最终我们能够得到res1(所有可能连的边),res2(各联通分量之间连起来的边),但是因为res2在求解的过程中,各联通分量会对同一条边计算两次,所以我们最终的答案为: ans = res1+res2/2-m;
    • 如果任意联通分量中存在非二分图,那么不论怎么加边都无法保证整个图内没有长度为奇数的回路,所以答案是0
  • 具体代码使用dfs实现即可

  • code

    // 染色 + 计数
    bool dfs(int u,int col){
    	g[u] = col;
    	c1 += col==1;
    	c2 += col==2;
    	for(auto v:e[u]){
    		if(g[v] == g[u]) return false;
    		if(!g[v]){
    			if(!dfs(v,3-col)) return false;;
    		}
    	}
    	return true;
    }
    
    // main
    int main() {
    	for(int i = 1;i <= n;++i){
    		if(!g[i]){
    			c1 = c2 = 0;
    			if(!dfs(i,1)){//如果存在非二分图,无法加边
    				cout<<0<<endl;
    				return;
    			};
    			res1 += c1*c2;
    			res2 +=(c1+c2)*(n-c1-c2);
    		}
    	}
    	int ans = res1+res2/2-m;//第一二种情况合并起来,因为如果只有一个联通分量,res2为0
    }
    

第五场个人赛

AC:

  • A:模拟,给出两种操作:A跟随B或者A取消跟随B,然后询问A和B两人是否相互跟随,使用map<pair<int, int>, int>存储是否跟随即可
  • B:思维,模拟,每次可以整体更改所有的数或者更改一个数,那么可以使用一个set维护那些被整体更改过的数来防止TLE
  • C:模拟,给一个时间,询问最近的时间,该时间将小时的低位与分钟的高位更换之后还能是正常的时间,直接模拟枚举判断
  • D:图论,使用bfs遍历即可
  • F:签到题,给一些字符串和规则,判断他们是否合法

补题:

E题总是没做对,其他的还没补...

E:
  • 题意:手里有很多卡牌,第一张可以随意放到桌子上,之后每次放的卡牌必须与上一次放的卡牌点数相同或者+1 mod m,询问最后手里剩的牌的最小点数是多少

  • 做法:使用前缀和差分,遍历每一个手里的数,进行多个分支判断,具体代码:

    int main() {
        for (int i = 1; i <= n; i++)
        {
            if (cha[i] >= 2)
            {
                tmp = sum[i - 1] - sum[curst - 1];
                if (tmp >= res)
                {
                    st = curst;
                    ed = i - 1;
                    res = tmp;
                }
                curst = i;
            }
            if (i == n && cha[i] >= 2)
            {
                tmp = a[n];
                if (tmp >= res)
                {
                    st = n;
                    ed = n;
                    res = tmp;
                    curst = n;
                }
                if (tmp == m - 1 && a[1] < 1)
                {
                    long long te = 0;
                    for (int i = 1; i < curst; i++)
                    {
                        if (cha[i] <= 1)
                        {
                            te += a[i];
                        }
                        else
                            break;
                    }
                    tmp += te;
                    if (tmp > res)
                    {
                        cout << sum[n] - tmp << endl;
                        return 0;
                    }
                }
            }
            if (i == n && cha[i] <= 1)
            {
                tmp = sum[i] - sum[curst - 1];
                if (tmp >= res)
                {
                    st = curst;
                    ed = i;
                    res = tmp;
                }
            }
        }
        if (ed == n && a[n] == m - 1 && a[1] < 1 && st > 1)
        {
            long long te = 0;
            for (int i = 1; i < st; i++)
            {
                if (cha[i] <= 1)
                {
                    te += a[i];
                }
                else
                    break;
            }
            res += te;
        }
        cout << sum[n] - res << endl;
    }
    

第六场个人赛

AC:

  • A:模拟,思维,给一棵树,第 $i$ 个节点的儿子是 $2i$ 和 $2i+1$ ,求每个节点的深度,关键代码:

    dep[(i + 1) * 2] = dep[a[i]] + 1;
    dep[(i + 1) * 2 + 1] = dep[a[i]] + 1;
    
  • B:dp,将横坐标纵坐标分开考虑,$dpx(i, j)$ 表示在x方向上,通过前 $i$ 个线段能否到达 $j$ 坐标,注意坐标要加10000的偏移量,保证非负,状态转移:dpx[i][j] = dpx[i - 2][j - p[i]] | dpx[i - 2][j + p[i]],纵坐标同理

  • D:枚举,数据量较小,暴力

  • E:简单题,给一个数组,问任意两个和最大且为偶数,输出和,正确解法为将奇数和偶数分开来存,然后奇数最大的两个加,偶数最大的两个加,再取max。wa了一发的原因是没有分开讨论,直接用一整个数组进行从大到小的枚举。

补题:

G:
  • 最初是在(1,1)的位置上面,每一次移动只能移动到与该点距离的平方为m的位置,问是否能到达所有的位置,要是可以,输出到达所有的位置的最小步数,要是不行,输出-1。

  • 使用bfs,先初始化所有位置的步数为最大值,存储到达所有位置的最小路径,如果说走完之后还有点的步数等于最大值,则输出-1,否则输出这个棋盘。

  • 核心代码:

    void bfs() {
    	q.push({0, 0});
    	while(!q.empty()) {
    		int x = q.front().first, y = q.front().second;
    		q.pop();
    		for (int i = 0; i < dx.size(); i++) {
    			int cntx = x+dx[i];
                int cnty = y+dy[i];
    			if(check(cntx, cnty)) continue;
    			if(dp[cntx][cnty] != -1) {
                    continue;
                }
    			dp[cntx][cnty] = dp[x][y] + 1;
    			q.push({cntx, cnty});
    		}
    	}
    }
    

第二场组队赛

因个人原因,只做了2题

AC:

  • G:每次取最大的数和最小的数,将最大的变成“大mod小”,如果是0,直接扔掉,问几次才能把整列数组的个数变为1;使用deque维护,复杂度 $O(nlogn)$

补题:

  • A:比较简单,差分+同余:

    int main() {
      	for(int i = 1; i < n; ++i) {
            cha[i] = a[i] - a[i - 1];
            // cout << cha[i] << " ";
        }
        // cout << endl;
        cha[0] = a[0];
    
        int g = gcd(cha[1], cha[2]);
        // cout << g << endl;
        for(int i = 3; i < n; ++i) {
            g = gcd(g, cha[i]);
            // cout << g << " ";
        }
        if(g == 1) cout << 2;
        else cout << 1;
    }
    
  • B:一开始以为是dp,但是数据量较小(5000),于是可以暴力枚举就行:

    int main() {
      	for(int i = l; i < s.size(); i++){
            if(s[i] == 'p'){
                for(int j = l; j <= i; j++){
                    if(s[j] == 'p') st[i - (j - l)] = 'd';
                    else st[i - (j - l)] = 'p';
                }
                if(st < ans) ans = st;
            }
        }
    }
    

训练

学习了一些基础的dp,总结了一些代码和文字:

  • 状压dp:状态压缩动态规划,就是我们俗称的状压DP,是利用计算机二进制的性质来描述状态的一种DP方式。
  • 例题:在 n×n(1<=n<=10) 的棋盘上放 k(0<=k<n×n)个国王,国王可攻击相邻的 8 个格子,求使它们无法互相攻击的方案总数。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=160;
int f[11][maxn][maxn];
int num[maxn],s[maxn];
int n,k,cnt;
void init(){  //预处理一下没有其他行限制下每一行的可能情况有多少种
	cnt=0;
	for(int i=0;i<(1<<n);i++){
		if(i&(i<<1)){   // 代表左右有相邻国王
			continue;
		}
		int sum=0;
		for(int j=0;j<n;j++){  //枚举一下i这个情况下哪些地方是国王
			if(i&(1<<j)){
				sum++;
			}
		}
		s[++cnt]=i;  //s[cnt]代表了第cnt种情况下的状态  
		num[cnt]=sum;
	}
//	cout<<"cnt "<<cnt<<"\n";
}
void solve(){
	cin>>n>>k;
	init();
	f[0][1][0]=1;  //代表第0行在num[1]即放了0个国王的情况有1种
	for(int i=1;i<=n;i++){  //枚举行
		for(int j=1;j<=cnt;j++){  //枚举这一行有多少种情况
			for(int l=0;l<=k;l++){   //枚举算上这一行的国王总数
				if(l>=num[j]){  //算上这一行放的国王总数起码得大于等于这一行自己就有的国王个数
					for(int t=1;t<=cnt;t++){  //枚举上一行的情况
						//1.不能跟上一行有列重合 2.不能刚好差一行 
						if(!(s[t]&s[j])&&!(s[t]&(s[j]<<1))&&!(s[t]&(s[j]>>1))){
							f[i][j][l]+=f[i-1][t][l-num[j]];
						}
					}
				}
			}
		}
	}
	int ans=0;
	for(int i=1;i<=cnt;i++){
		ans+=f[n][i][k];
	}
	cout<<ans<<"\n";
}
signed main(){
	int t;
	t=1;
	while(t--){
		solve();
	}
}
  • 数位dp:
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define maxn 15
int num;
int* a = new int[maxn];
int f[15];
//int a[maxn];
int b[maxn];//b保存第p为存的是那个数
int ten[maxn];
int L, R;
int t;
int dfs(int p, bool limit) {//p表示在第p位,limite表示此时是否处于限制位
	if (p < 0) {
		//for (int i = 2; i >= 0; i--)cout << b[i];//无限递归,记得加结束return
		//cout << endl;
		return 0;//搜索结束,返回
	}
	if (!limit && f[p] != -1) {//记忆化搜索,不处于限制位,并且f[p]被算过了
		return f[p];
	}
	int up = limit ? a[p] : 9;//判断是否处于限制位,如果是就只能取到a[p]为,否则最高位能取到9
 
	int ans = 0;
 
	for (int i = 0; i <= up; i++) {
		//b[p] = i;
		if (i == 3) {
			if (limit && i == up) {
				ans += 1;
				for (int j = p - 1; j >= 0; j--)//处于限制条件就把限制数下面全算上
					ans += a[j] * ten[j];
			}
			else//如果不处于限制条件直接加上10的p次方
				ans += ten[p];
		}
		else ans += dfs(p - 1, limit && i == up);//这里填a[p]可以填up也行,在处于限制的时候up等于a[p]
 
	}
	if (!limit)//记忆化搜索,如果没有处于限制条件就可以直接那算过一次的数直接用,能节省很多时间
		f[p] = ans;
	return ans;
}
 
int handle(int num) {
	int p = 0;
	while (num) {//把num中的每一位放入数组
		a[p++] = num % 10;
		num /= 10;
	}
	//说明a数组写进去了,但是读取无效数据是什么意思勒,之前好像不是这样的,解决办法,动态创建数组
	/*for (int i = 0; i < p; i++) {
		cout << a[i];
	}*/
	return dfs(p - 1, true);//对应的最高位为p-1位,为True表示没有处于限制位
}
 
void init() {
	ten[0] = 1;
	for (int i = 1; i < 15; i++) {
		ten[i] = ten[i - 1] * 10;
	}
	memset(f, -1, sizeof(f));
}
int32_t  main() {
	cin>>t;
    while(t--){
        cin>>L>>R;
        //handle(23);
	    init();//一定要记得初始化,TM的我在这卡了半个月
	    cout << handle(R)-handle(L) << endl;
	    delete[]a;
    }
    return 0;
}

标签:总结,tmp,num,训练,int,long,第二周,maxn,dp
From: https://www.cnblogs.com/marti88414/p/17569377.html

相关文章

  • ADS简单模型参数总结
    MIM电容(金属-介质-金属)2.实验室用多层电介质电容(DielectricLaboratoriesMulti-LayerChipCapacitor)3.叉指电容(2portsor4ports)4.微波薄膜电容(MicrostripThinFilmCapacitor)5.三层衬底带状桥方型电感(MicrostripRectangularInductor(StripBridge,3-......
  • RF射频PCB板布局布线经验总结
    射频(RF)电路板设计由于在理论上还有很多不确定性,因此常被形容为一种“黑色艺术”,但这个观点只有部分正确,RF电路板设计也有许多可以遵循的准则和不应该被忽视的法则。 不过,在实际设计时,真正实用的技巧是当这些准则和法则因各种设计约束而无法准确地实施时如何对它们进行......
  • 小分支职场网络覆盖案例总结
    需求描述1.AP部分: AP数量较少,考虑到成本,AP使用FAT模式。2.交换机部分:下联接入有线网部分和AP部分。3.防火墙部分:网关、DHCP、NAT具体配置1.AP部分====修改AP工作模式====****查看AP工作模式****[CN-SZBW-1F-OFFICE-AP11]displaywlandeviceroleCurrentrunningmo......
  • 七月份集训总结
    七月份集训总结前言今天被拉到办公室里头一个个总结了一下集训的收获和感想。emm,是该总结总结了。感想自己马上就要从准高二成为真正的高二学生了,时间真的蛮快的。不知道去年的霜木看到今天的自己,还会不会选择竞赛呢?收获&不足平衡树的一些应用KD-Tree(目前只会静态的模板......
  • 代码随想录训练营 Day01- 数组(上)
    概述第一天主要学习的是数组相关的内容,相关学习的内容包括数组的基本特性的学习,二分搜索方法的学习。数组特点数组的基本特点包括:下标从0开始内存连续性(Java中定义数组需要直接声明其空间大小)数组元素不可以删,只能覆盖ArrayList底层是数组实现,其实际上应该叫一......
  • 语言模型的预训练[6]:思维链(Chain-of-thought,CoT)定义原理详解、Zero-shot CoT、Few-s
    大语言模型的预训练[6]:思维链(Chain-of-thought,CoT)定义原理详解、Zero-shotCoT、Few-shotCoT以及在LLM上应用1.思维链定义背景在2017-2019年之间,随着Transformer模型的提出,计算资源与大规模语料库不断出现,自然语言处理领域发生了翻天覆地的变化,传统的全监督学习的范......
  • 【禅道2023年中总结】用热爱,走一些“远”路!
    相伴:开源十四载,更适合成长中企业的项目管理工具盛夏来临,2023年也过去了一半。回顾上半年,禅道团队不断突破,拥抱变化,迎接新的机遇和挑战,一些来之不易的突破,让我们惊叹、思考或感动……时光的车轮滚滚向前,14岁的禅道青春正好。这十余年间,虽然历经过波折与磨难,禅道却依然保持着顽强的......
  • Tita 升级|总结支持导入项目
    升级详情Tita-OKR和新绩效一体化管理平台一、【总结模板】新增「项目进展」组件管理可在总结模板中配置「项目进展」组件,可自定义组件名称与导入条件二、【写总结】模板配置项目组件后,支持项目导入与更新写总结时使用的模板包含「项目进展」组件时,点击开启「工作项目」......
  • ASP.NET Core 系列总结 -- 系列文章
    《ASP.NETCore》系列文章基于.NET3.1和.NET6,主要是系统总结自己日常工作和学习中的知识点,之前是自己在OneNote上自己写,作为学习、总结笔记,逐渐放出来也供大家参考,希望大家都能够对ASP.NETCore框架有一个清晰的认知。章节目录1.入口文件ASP.NETCore-入口文......
  • 7.19总结
    今天还是无心学习,那就做了最基础的配置应用,将maven导入idea(虽然知道idea自己有),但我不懂,就按照视频说的下载了另外的,在创建maven芯模块的时候,他说不支持版本,然后视频也没讲解,我就在csdn上面搜了搜,终于找到解决办法,原来是我idea配置的java编辑器版本很低,我就换了稍微高点的版本,最后......