【codeforces】Round #520 (Div. 2) A+B+C+D

目录

A - A Prank

B - Math

C - Banh-mi

D - Fun with Integers


【A - A Prank】

题目链接:http://codeforces.com/contest/1062/problem/A

【题意】

给你一串序列,长度为n,在1-1000范围内严格递增。

问最多在序列中删掉多少元素可以使填数的方式唯一(仍然为严格递增序列)

如12345,就可以删掉中间的234变成1_ _ _5,要求填进去的数仍然满足严格递增,就只能填2 3 4。

【分析】

遍历一遍数组,因为范围是1-1000,那么使得a[0]=0,a[n+1]=1001,最后求得的长度len-2即是所需要的长度。加上这两个元素是为了考虑如果开始和最后都可以删除的情况。

【代码】

#include<bits/stdc++.h>
using namespace std;

const int maxn=1e2+5;
int a[maxn];

int main()
{
	int n;scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	a[0]=0;a[n+1]=1001;
	int len=1,pre=0,ans=0;
	for(int i=1;i<=n+1;i++)
	{
		if(pre+1==a[i])
			len++,pre++;
		else
		{
			ans=max(len-2,ans);
			len=1;	
			pre=a[i];
		}
	}
	ans=max(ans,len-2);
	printf("%d\n",ans);
	return 0;
}

【B - Math】

题目链接:http://codeforces.com/contest/1062/problem/B

【题意】给你一个数字,有两种操作:

  1. 乘x(x为任意正整数)
  2. 开方

每次只能执行一种操作,求可以获得的最小数和操作的次数。

【分析】自己列几个例子,就可以发现可以得到的最小的数字是该数所有的质因数的乘积(divide函数分解质因数),最小的操作次数就是求每个质因数的幂数,然后将其化成最小的2的幂次。举几个例子就可以看出来了。即所有的质因数的指数部分都是偶数,然后通过乘以X来使其达到所有质因数的指数都是2的次幂,最后不断开平方,得到我们想要的答案。

【代码】

#include<bits/stdc++.h>
using namespace std;

const int maxn=1e5;
int p[maxn],c[maxn];//p[i]存质因数,c[i]存指数 

int len;

int divide(int n)//质因数分解 
{
	int cnt=0;
	for(int i=2;i*i<=n;i++)
	{
		if(n%i==0)
		{
			p[++cnt]=i;
			c[cnt]=0;
			while(n%i==0)
			{
				n/=i;
				c[cnt]++;
			}
		}
	}
	if(n>1) 
		p[++cnt]=n,c[cnt]=1;
	len=cnt;
	int pp=1;
	for(int i=1;i<=cnt;i++) pp*=p[i];
	return pp;//返回质因数之积 
}

int main()
{
	len=0;
	int q=1;
	int aa[32]={0};//存2的i次幂对应的数 
	aa[0]=1;
	for(int i=1;i<32;i++)
		q*=2,aa[i]=q;
	memset(p,0,sizeof(p));
	memset(c,0,sizeof(c));
	
	int n;scanf("%d",&n);
	
	int ans1=divide(n);
	int ans2=0;
	
	sort(c+1,c+1+len);
	int mm=c[len],index=0;
	for(int i=1;i<32;i++)
	{
		if(aa[i]>=mm)
		{
			index=i;break;
		}
	}
	ans2=index;
	if(mm!=c[1])index++;
	if(aa[index]!=mm)ans2++;  
	if(ans1==n)ans2=0;                                                  
	cout<<ans1<<" "<<ans2<<endl;
	
	return 0;
}

【C - Banh-mi】

题目链接:http://codeforces.com/contest/1062/problem/C

【题意】给你一个01串,q次询问给出区间[l,r],每次拿掉一个数字获得相对应数字的分数,并使其他位增加相对应的分数。求最高可以获得的分数。

【分析】对于每个区间贪心,先拿1,再拿0;设该区间1的个数为x,自己列几个例子就可以发现,

依次取1的时候等比数列:1,2,4,...,2^x-1

依次取0的时候等比数列:2^x-1,2(2^x-1),4(2^x-1),...

做数学运算,各求其前n项和,相加,得最后结果是:(2^x-1)2^(len-x);

所以,要用到快速幂

并且,每次都是要用到区间里1的个数,如果每次都求一遍的话会超时,所以,预处理一下1的个数,前缀和

【代码】

#include<cstring>
#include<iostream>
#include<string>
#include<cstdio>
#include<algorithm>
using namespace std;

#define ll long long
const ll mod=1e9+7;
const ll maxn=1e5+5;

char s[maxn];
int num[maxn];//记录该位之前1的个数 

ll qpow(ll a,ll b)
{
	ll ans=1;
	while(b)
	{
		if(b&1)ans=ans*a%mod;
		a=a*a%mod;
		b/=2;
	}
	return ans%mod;
}

int main()
{
	int n,q;
	scanf("%d%d",&n,&q);
	scanf("%s",s+1);
	num[0]=0;
	for(int i=1;i<=n;i++)
		num[i]+=num[i-1]+(s[i]=='1'?1:0);
	int l,r;
	while(q--)
	{
		int len=0,x1=0;
		scanf("%d%d",&l,&r);
		len=r-l+1;
		x1=num[r]-num[l-1];
	//	cout<<"x1="<<x1<<endl;
		ll ans=(qpow(2,x1)-1)%mod * (qpow(2,len-x1)%mod)%mod;
		printf("%lld\n",ans);
	}
	return 0;
}

【D - Fun with Integers】

题目链接:http://codeforces.com/contest/1062/problem/D

【题意】输入一个正整数n,求[2,n]区间内绝对值成倍数关系整数对的和。

如,[2,5],有2,4;2,-4;-2,4;-2,-4四组,每组倍数的绝对值是2,所以最终答案是2×4=8;

【分析】枚举。但是枚举也要注意方法,不然还是会超时的。我一开始直接俩循环,外层套i,内层套与i成倍数的数从i*2~n但这样显然!会超时!!蠢死了   就直接内层是倍数并约束i*j<=n,这样会少了很多循环,然后这个倍数乘4就好了

【代码】

#include<cstring>
#include<iostream>
#include<string>
#include<cstdio>
#include<algorithm>
using namespace std;

typedef long long ll;

int main()
{
	ll n;scanf("%lld",&n);
	ll n2=n/2,ans=0;
	for(ll i=2;i<=n2;i++)
		for(ll j=2;i*j<=n;j++)
			ans+=j*4;
	printf("%lld\n",ans);
	return 0;
}
 
 
 

猜你喜欢

转载自blog.csdn.net/qq_38735931/article/details/84187745