23.11.26周报(重庆省赛准备阶段)

星期一:

军训结束,正式成为一名退伍老兵。若有战,召必回!

12月16号考六级,17号重庆市赛,这个月得狠狠上强度啊。

话接上回的B题:

题意:乍看差点以为是道树题,差点直接run了。还好先读完了题。一棵未知的树,有bfs经过的点的顺序,求可能树的最小高度。bfs对于同一父节点的所有点升序访问。

思路:这题的样例给的极其简单,导致我先交了发极其简单的代码,wa2。随即发现情况并不止样例这么简单,不过也就是道模拟。

代码如下:

#include <bits/stdc++.h>
using namespace std;
using ll=long long;
using PII=pair<int,int>;

const int N=2e5+10;
int n;
int a[N];
int ans,las,tmp;
void solve(){
	ans=1;las=1;tmp=1;
	cin >> n;
	for(int i=1;i<=n;i++){
		cin >> a[i];
	}
	for(int i=3;i<=n;i++){
		if(a[i]>a[i-1]){
			tmp++;
		}else{
			las--;
			if(!las){
				ans++;
				las=tmp;
				tmp=1;
				continue;
			}
			tmp++;
		}
	}
	cout << ans << endl;
}
int main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int t=1;
	cin >> t;
	while(t--) solve();
	return 0;
}
//make it count
//开ll plz

星期二和李,强打了场广西市赛,效果还不错。

比赛B题:

题意:自行理解

思路:给2做个特判,其余为26 0 26的n次幂-26。所以需要用到快速幂,这里记录一个%的细节

代码如下:

#include <bits/stdc++.h>
using namespace std;
using ll=long long;
using PII=pair<int,int>;

const int N=2e5+10;
const ll mod=1e9+7;
int n;
int a[N];
ll ask(ll a,ll n,ll m){
	if(n==0) return 1;
	if(n==1) return a;
	ll s=ask(a,n/2,m);
	s=s*s%m;
	if(n%2==1) s=s*a%m;
	return s;
}
void solve(){
	cin >> n;
	if(n==2){cout << "26 650 0"; return ;}
	ll ans=(ask(26,n,mod)-26+mod)%mod;
	cout << "26 0 " << ans;
}
int main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int t=1;
//	cin >> t;
	while(t--) solve();
	return 0;
}
//make it count
//开ll plz

这里有一个需要注意的地方,就是这句

	ll ans=(ask(26,n,mod)-26+mod)%mod;

当时一开始写的是

	ll ans=ask(26,n,mod)-26;

没有考虑到的是,ans在取模后可能是一个小于26的值,所以减26后可能小于0,所以需要再加一个mod再取模一次。比赛时因为没考虑到这点,感觉被耽误了可能得有1个小时。消耗的不止时间,还有精力,搞的后面没力气做题了。

再记录下学到了的一道题:

题意:判断能否仅通过复制粘贴将字符串s变为t(复制只能全选)

思路:按我的思路来的话,需要遍历一下t,遍历到不相同的字符会退出,遍历完后判断t是否为s的2次幂数倍。但在网上看到了个更牛的思路,直呼学到了。

代码如下:

#include <bits/stdc++.h>
using namespace std;
using ll=long long;
using PII=pair<int,int>;

const int N=1e5+10;
int n;
string s,t;
void solve(){
	cin >> s >> t;
	while(s.size()<t.size()) s+=s;
	if(s==t) cout << "win";
	else cout << "failure";
}
int main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int t=1;
	//cin >> t;
	while(t--) solve();
	return 0;
}
//make it count
//开ll plz

直接模拟,非常美丽的思路和代码啊。

再补俩题:

H题:

题意:寻找满足条件的正整数有多少个,条件如下。给一a,x不大于a。给m个b和c,b%x=c。

思路:一开始想的是,对于每次b,c,找出b-c的因数集合,对所有集合取交集。但wa

代码如下:

#include <bits/stdc++.h>
using namespace std;
using ll=long long;
using PII=pair<int,int>;

const int N=1e5+10,M=1e8;

void solve(){
	ll m,maxx,minn=0;
	ll ans=0;
	vector<pair<int,bool>>ve;
	cin >> m >> maxx;
	for(int i=1;i<=m;i++){
		ll b,c;
		cin >> b >> c;
		minn=max(c,minn);
		if(i==1){
			for(int j=1;j*j<=(b-c);j++){
				if((b-c)%j==0){
					if(j<=maxx) ve.push_back({j,1});
					if(j*j==b-c) break;
					if((b-c)/j<=maxx) ve.push_back({(b-c)/j,1});
				}
			}
			continue;
		}
		
		for(int j=0,k=ve.size();j<k;j++){
			if(b==0) continue;
			if((b-c)%ve[j].first) ve[j].second=0;
		}
	}
	for(int i=0,j=ve.size();i<j;i++){
		if(ve[i].second && ve[i].first>minn && ve[i].first<=maxx) ans++;
	}
//	for(int i=0,j=ve.size();i<j;i++){
//		cout << ve[i].first << " " << ve[i].second << endl;
//	}
	cout << ans;
}
int main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int t=1;
	//cin >> t;
	while(t--) solve();
	return 0;
}
//make it count
//开ll了没

然后看题解,发现可以取所有b-c的gcd,效果是一样的,且方便实现。(也不是很方便

代码如下:

#include <bits/stdc++.h>
using namespace std;
using ll=long long;
using PII=pair<int,int>;

const int N=1e5+10,M=1e8;
int m;
ll a,minn=1;
ll gc,ans;
int gcd(int a,int b){
	return b==0?a:gcd(b,a%b);
}
void solve(){
	cin >> m >> a;
	while(m--){
		ll b,c;
		cin >> b >> c;
		gc=gcd(b-c,gc);
		minn=max(c,minn);
	}
	if(!gc){cout << a-minn; return ;}
//	for(int i=1;i<=gc/i;i++){
//		if(gc%i==0 && gc/i>minn && gc/i<=a) ans++;
//	}
	for(int i=1;i<=gc/i;i++){
		if(gc%i==0){
			if(i<=a && i>minn) ans++;
			if(gc/i!=i && gc/i<=a && gc/i>minn) ans++;
		}
	}
	cout << ans;
}
int main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int t=1;
	//cin >> t;
	while(t--) solve();
	return 0;
}
//make it count
//开ll了没

D题:

题意:3n个人组成n个队伍,给出m对熟悉关系,间接熟悉也算熟悉,每人的焦虑值为同队中不熟悉的人的数量,问焦虑值总和的最小。

思路:并查集,但很久没写并查集了,刚好练练。

代码如下:

#include <bits/stdc++.h>
using namespace std;
using ll=long long;
using PII=pair<int,int>;

const int N=3e6+10;
int n,m;
int fa[N],num[N];
int a,b,ans;
int fnd(int x){
	return x==fa[x]?x:fa[x]=fnd(fa[x]);
}
void solve(){
	cin >> n >> m;n*=3;
	for(int i=1;i<=n;i++) fa[i]=i,num[i]=1;
	while(m--){
		int x,y;
		cin >> x >> y;
		x=fnd(x),y=fnd(y);
		if(x!=y){
			fa[x]=y;
			num[y]+=num[x];
		}
	}
	for(int i=1;i<=n;i++){
		if(fa[i]==i){
			if(num[i]%3==1) b++;
			if(num[i]%3==2) a++;
		}
	}
//	cout << a << " " << b << endl;
	if(a>=b) ans=b*4+(a-b)/3*8;
	else ans=(a+b)*2;
	cout << ans;
}
int main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int t=1;
	//cin >> t;
	while(t--) solve();
	return 0;
}
//make it count
//开ll plz

不过目前我还没搞懂 ans=(a+b)*2 怎么来的。

再补几道比赛没来得及看,但也许可以做做的题。

看了下,好像补不是很了。

星期四:

20号(星期一的每日三题:

A题:

题意:自行理解

思路:数据不大,思路难想。我最开始的思路是对于每个ti,向两边扩散寻找取出时间,但wa2,思路错了

记录下代码:

#include <bits/stdc++.h>
using namespace std;
using ll=long long;
using PII=pair<int,int>;

const int N=2e5+10,M=1e9+10;
const int mod=998244353;
int n;
int a[210];
bool vi[1000];
int ans;
void solve(){
	memset(vi,0,sizeof(vi));
	ans=0;
	cin >> n;
	for(int i=1;i<=n;i++){
		cin >> a[i];
	}
	sort(a+1,a+n+1);
	for(int i=1;i<=n;i++){
		int j=a[i],k=a[i];
		while(vi[j] && vi[k]){
			j--,k++;
			if(j==0) j++;
		}
		if(!vi[j]) vi[j]=1,ans+=a[i]-j,cout << j << endl;
		else vi[k]=1,ans+=k-a[i],cout << k << endl;
//		for(int y=1;y<=6;y++) cout << vi[y] << " ";cout << endl;
	}
	cout << ans << endl;
}
int main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int t=1;
	cin >> t;
	while(t--) solve();
	return 0;
}
//make it count
//开ll plz

去hack了下数据,发现是道1800的题,且有dp标签,尝试从dp角度切入。

。。。(我讨厌dp)

啃了半天题解,做不了一点,麻了。

记录下学到的memset函数初始化最大值

memset(a,0x3f,sizeof(a));

经过半天(字面意义上),终于勉强算是拿下了这道dp。

dp[i][j]表示考虑到前i个菜,在j时刻最小不新鲜值。dp数组的初始化需要注意。

代码如下:

#include <bits/stdc++.h>
using namespace std;
using ll=long long;
using PII=pair<int,int>;

const int N=2e5+10,M=1e9+10;
const int mod=998244353;
int n;
int a[210];
int dp[210][440];
int ans;
void solve(){
	memset(dp,0x3f,sizeof(dp));
	ans=INT_MAX;
	cin >> n;
	for(int j=0;j<=2*n;j++) dp[0][j]=0;
	for(int i=1;i<=n;i++){
		cin >> a[i];
	}
	sort(a+1,a+n+1);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n*2;j++){
			dp[i][j]=min(dp[i][j-1],dp[i-1][j-1]+abs(a[i]-j));
		}
	}
//	for(int j=1;j<=2*n;j++) ans=min(dp[n][j],ans);
	cout << dp[n][n*2] << endl;
}
int main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int t=1;
	cin >> t;
	while(t--) solve();
	return 0;
}
//make it count
//开ll plz

星期五:

题意:自行理解

思路:

(一天拿不下一道题,woyouzui)

晚上打了场div2,找时间补补c和d题

星期六打了场复活赛,比较有悬念地拿下了,但过的都是基础题,胜在罚时。

记录一个getline相关的操作,今一题遇到需要用到getline的情况,但cin.clear()好像没起作用,所以我把cin换成了scanf,还是不行。该怎么操作呢,如下(在cin之后使用):

    s="\n";
	getline(cin,s);

第二天回想起,cin和getline混用,不是用cin.clear(),是用cin.ignore() 啊,佛了

记录一道有价值的题,赛时没a,赛后补的,比较吃细节。

题意:自行理解

思路:我最开始想到的是贪心模拟,二分貌似也行,先不管。

代码如下:

#include <bits/stdc++.h>
using namespace std;
using ll=long long;
using PII=pair<int,int>;

const int N=2e5+10;
const int mod=998244353;
int n,m;
ll maxx,minn;
bool iff,iif;
void solve(){
	int c,d;	
	cin >> n;
	cin >> c >> d;
	if(d==1) iif=1,minn=1900;
	else iff=1,maxx=1899;
	minn+=c,maxx+=c;
	for(int i=2;i<=n;i++){
		cin >> c >> d;
		if(d==1){
			if(iff && maxx<1900){cout << "Impossible"; return ;}
			if(!iif) iif=1,minn=1900;
			minn+=c,maxx+=c;
		}else{
			if(iif && minn>=1900){cout << "Impossible"; return ;}
			if(!iff) iff=1,maxx=1899;
			if(maxx>1899) maxx=1899;
			minn+=c,maxx+=c;
		}
	}
	if(!iff){cout << "Infinity"; return ;}
	cout << maxx;
}
int main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int t=1;
	//cin >> t;
	while(t--) solve();
	return 0;
}
//make it count
//开ll了没

还有E,F,I题都可以补。

星期天打了场沙东省赛,花了两小时,做了5道签到题就run了,罚时很不理想,主要有两道题犯病了,耽误了时间。记录一道签到题犯病过程:

题意:初始有n金币,每次死亡掉一半,向上取整需注意,问死k次后剩多少金币。

思路:开始时脑阔短路,觉得直接模拟会tle。。嗯是让我搞了个莫名其妙的式子出来,后来强模拟时用double和ceil函数,wa2了,就给改成了int和手动ceil,ac。真耽误了很多时间这里,本来应该秒的

晚上打了场div2,第一次过3题,舒服.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值