2021牛客寒假算法基础训练营2

官方题解

D牛牛与整除分块

原题链接

sqrt(n)是分割线。算出来S的个数然后减

#include<bits/stdc++.h>

using namespace std;
const int N=1e5+5;
int main()
{
	int n,t,x;
	scanf("%d",&t);
	while(t--){
		scanf("%d%d",&n,&x);
		int cnt=(int)sqrt(n)+(int)sqrt(n-(int)sqrt(n));
	//	cout<<cnt<<'\n';
		if(x<=sqrt(n))cout<<x;
		else cout<<(int)(cnt-n/x+1);
		cout<<'\n';
	}
//	int n;
//	cin>>n;
//	for(int i=1;i<=n;i++){
//		vector<int>s;
//		set<int>st;
//		for(int j=1;j<=i;j++){
//			s.push_back(i/j);
//			st.insert(i/j);
//		}
//		for(auto x:s){
//			cout<<x<<' ';
//		}
//		cout<<"cnt="<<st.size()<<'\n';
//		cout<<'\n';
//	}
	
  return 0;
}

G牛牛与比赛颁奖

map+差分

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N=2e5+5;
map<int,int>mp;
int cot[N];//通过i题的队伍人数 
int main()
{
	int n,m;
	cin>>n>>m;
	int l,r;
	for(int i=0;i<m;i++){
		cin>>l>>r;
		mp[l]++;
		mp[r+1]--;
	}
	int linej=0,liney=0,linet=0,j=ceil(1.0*n/10),y=ceil(1.0*n/4),t=ceil(1.0*n/2);
	int last=1,cnt=0,maxx=0;
	for(auto it:mp){
		cot[cnt]+=it.first-last;
		last=it.first;
		cnt+=it.second;
		maxx=max(maxx,cnt);
	}
	//cout<<j<<' '<<y<<' '<<t<<'\n';
	for(int i=maxx;i>=0;i--){
		cot[i]+=cot[i+1];
		if(cot[i]>=j&&!linej)linej=max(1,i);
		if(cot[i]>=y&&!liney)liney=max(1,i);
		if(cot[i]>=t&&!linet)linet=max(1,i);
		//cout<<cot[i]<<' ';
	}
	//cout<<'\n';
	//cout<<linej<<' '<<liney<<' '<<linet<<'\n';
	cout<<cot[linej]<<' '<<cot[liney]-cot[linej]<<' '<<cot[linet]-cot[liney]<<'\n';
  return 0;
}
/*
1 1
1 1
1 0 0
*/

H牛牛与棋盘

签到题

#include<bits/stdc++.h>

using namespace std;
const int N=1e3+5;
int vis[N][N],col[N][N],n;
int dir[4][2]={0,1,1,0,0,-1,-1,0};
void dfs(int x,int y)
{
	for(int i=0;i<4;i++){
		int xx=x+dir[i][0];
		int yy=y+dir[i][1];
		if(xx>=0&&xx<n&&yy>=0&&yy<n&&!vis[xx][yy]){
			vis[xx][yy]=1;
			col[xx][yy]=col[x][y]^1;
			dfs(xx,yy);
		}
	}
}
int main()
{
	cin>>n;
	col[0][0]=0;
	vis[0][0]=1;
	dfs(0,0);
//	for(int i=0;i<n;i++){
//		for(int j=0;j<n;j++){
//			if(!vis[i][j]){
//				dfs(i,j);
//			}
//		}
//	}
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			cout<<col[i][j];
		}
		cout<<'\n';
	}
  return 0;
}

I牛牛的“质因数”

原题链接

这道题用O(nsqrt(n))是过不去的,人家就卡这个,所以普遍做法就是用线性筛筛出1-n的素数,然后分解质因数(分解质因数不能是sqrt(n)),用打表出来的筛可以卡过去。这里的做法是用官方题解给出的筛法树来做的。具体就是线性时间内建树,用fa[x]标记x的父亲,质数的父亲都是1,fa_edge_prime[x]标记x的最小质因子,这样就能在logn下筛出X的所有质因子,然后数字拼接算出答案。总的时间复杂度O(nlogn)。其中还有拼接的复杂度没被算进去,刚好可以卡过去。难点其实就在于建树。官方题解解释的很详细。第一次知道线性筛可以构建筛出质因子的树=~=

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll ans;
const int N=4e6+5,mod=1e9+7;
int n,prime[N],vis[N],fa[N],fa_edge_prime[N];
void prime_()
{
    for(int i=2;i<=n;i++){
        if(!vis[i]){
        	prime[++prime[0]]=i;
        	fa[i]=1;
        	fa_edge_prime[i]=i;
		}
        for(int j=1;j<=prime[0]&&i*prime[j]<=n;j++){
        	vis[i*prime[j]]=1;
        	fa_edge_prime[i*prime[j]]=prime[j];
        	fa[i*prime[j]]=i;
            if(i%prime[j]==0)break;
        }
    }
}
ll fun(int x)
{
	vector<int>v;//统计质因子 例如26=2,13
	while(x!=1){
		v.push_back(fa_edge_prime[x]);
		x=fa[x];
	}
	ll res=0,j=1;
	for(int i=v.size()-1;i>=0;i--){
		ll temp=v[i];
		while(temp){//26=213,因此位数>1的需要循环求
			ll t=temp%10;
			res=(res+t*j%mod)%mod;
			j=j*10%mod;
			temp/=10;
		}
	}
	return 1ll*res;
}
int main()
{
	//freopen("out.txt","w",stdout);
	cin>>n;
	prime_();
	for(int i=2;i<=n;i++){
		if(!vis[i])ans=(ans+i)%mod;
		else ans=(ans+fun(i))%mod;
	}
	cout<<ans<<'\n';
  return 0;
}
/*
1000000
631719342

100100
835426760

10000
297701107
*/

方法2:埃氏筛+dp

f[x]=f[x/pi]*10^(len(pi))+pi(pi是x的最大质因子)。

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N=4e6+5,mod=1e9+7;
ll f[N],n;
ll cal(ll x)
{
	ll t=10;
	for(int i=1;i<=x;i++)
	t=t*10%mod;
	return t;
}
void prime_()
{
	for(int i=2;i<=n;i++){
		if(!f[i]){
			f[i]=i;
			for(int j=2*i;j<=n;j+=i)
			f[j]=(f[j/i]*cal(log10(i))%mod+i)%mod;
		}
	}
}
int main()
{
	cin>>n;
	prime_();
	ll ans=0;
	for(int i=2;i<=n;i++)
	ans=(ans+f[i])%mod;
	cout<<ans<<'\n';
  return 0;
}

J牛牛想要成为hacker

原题链接

前一段填充斐波那契数列,后边填充比前边小的即可。因此把菲波那切数列中前2个挪到后面即可

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N=1e3+5;
ll f[N];
int main()
{
	int n;
	cin>>n;
	f[1]=2;f[2]=3;
	for(int i=3;i<=42;i++){
		f[i]=f[i-1]+f[i-2];
	}
	int cnt=0;
	for(cnt=1;cnt<=min(n,42);cnt++){
		cout<<f[cnt]<<' ';
	}
	for(int i=cnt;i<=n;i++){
		cout<<1<<' ';
	}
	cout<<'\n';
  return 0;
}
//46

猜你喜欢

转载自blog.csdn.net/qq_43566782/article/details/113665689
今日推荐