Codeforces Round #520 (Div. 2) A B C D

A. A Prank

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

题目大意:n个数,输入n个数,然后对于这些数,看最多能够擦除多少个数,还能还原出原数组。

这些数范围:1~1000。

方法:下标相减==里面的元素值相减则是能够删掉的,然后特判一下头和尾(取其中能够删除最多的元素)

//#pragma comment(linker, "/STACK:1024000000,1024000000") 
 
#include<stdio.h>
#include<string.h>  
#include<math.h>  
#include<stdlib.h>

//#include<map>   
//#include<set>
#include<deque>  
#include<queue>  
#include<stack>  
#include<bitset> 
#include<string>  
#include<fstream>  
#include<iostream>  
#include<algorithm>  
using namespace std;  
 
#define ll long long  
//#define max(a,b) (a)>(b)?(a):(b) 
//#define min(a,b) (a)<(b)?(a):(b) 
#define clean(a,b) memset(a,b,sizeof(a))// ˮӡ 
//std::ios::sync_with_stdio(false); 
const int MAXN=1e5+5; 
const ll INF=1e18;  
const ll mod=1e9+7;  

int arr[MAXN];

int main()
{
	std::ios::sync_with_stdio(false); 
	int n;
	while(cin>>n)
	{
		for(int i=1;i<=n;++i)
			cin>>arr[i];
		int ans=0,res=0;
		int res1=0,res2=0;//头和尾的可删除元素个数
		for(int i=1,j=1;i<=n;++i)
		{
			if((arr[i]-arr[j])==i-j)//删除一个区间
			{
				if(i-j>1)
					res++;
			}
			else//到该点结束
			{
				if(arr[j]==1&&i-j>1&&j==1)//特判1~i区间
					res1=res+1;
				ans=max(ans,res);//取最大的区间
				j=i;//刷新
				res=0;
			}
		}
		if(arr[n]==1000&&arr[n-1]==999)//特判末尾区间
			res2=res+1;
		if(arr[1]==1&&arr[n]==n)//特判从头到尾1~n
			res1=n-1;
		ans=max(ans,res);
		ans=max(ans,res1);
		ans=max(ans,res2);
		cout<<ans<<endl;
	}
}

B. Math

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

题目大意:给出一个n,然后有两种操作,1.乘上一个数   2.对这个数开平方。求只用这两个操作得出的最小值,并且输出操作次数。

思路:把这些数的素因子提取出来,因为只能开根,因此如果素因子的次幂都是1的话就是最小值了,答案就是所有的素因子的乘积,

至于此树,所以我们可以首先将它乘上一个数,使得所有的素因子的次幂都是2的倍数,然后开2的倍数的平方即可

//#pragma comment(linker, "/STACK:1024000000,1024000000") 
 
#include<stdio.h>
#include<string.h>  
#include<math.h>  
#include<stdlib.h>

//#include<map>   
//#include<set>
#include<deque>  
#include<queue>  
#include<stack>  
#include<bitset> 
#include<string>  
#include<fstream>  
#include<iostream>  
#include<algorithm>  
using namespace std;  
 
#define ll long long  
//#define max(a,b) (a)>(b)?(a):(b) 
//#define min(a,b) (a)<(b)?(a):(b) 
#define clean(a,b) memset(a,b,sizeof(a))// ˮӡ 
//std::ios::sync_with_stdio(false); 
const int MAXN=1e6+5; 
const ll INF=1e18;  
const ll mod=1e9+7;  

int vis[MAXN];

int main()
{
	std::ios::sync_with_stdio(false); 
	int n;
	while(cin>>n)
	{
		clean(vis,0);
		int ans=1;
		for(int i=2;i<=n;++i)//求素因子
		{
			if(n%i==0)
				ans=ans*i;
			while(n%i==0)//求出素因子的次幂
			{
				vis[i]++;
				n=n/i;
			}
		}
		if(n>1)
			vis[n]++;
		int maxnum=0;
		for(int i=1;i<MAXN;++i)//找出最大的那个次幂
			maxnum=max(maxnum,vis[i]);
		int i=1,oper=0;
		while(i<maxnum)//判断开平方多少次
		{
			i=i<<1;
			oper++;
		}
		maxnum=i; //乘上去
		int f=0;//是否不用乘
		for(int j=1;j<MAXN;++j)
		{
			if(maxnum!=vis[j]&&vis[j])//要乘以一个数
			{
				f=1;
				break;
			}
		}
		if(f)//要乘+1
			cout<<ans<<" "<<oper+1<<endl;
		else//不用乘
			cout<<ans<<" "<<oper<<endl;
	}
}

C. Banh-mi

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

题目大意:给出n个长度的01串和q次询问,对于每次询问,输入一个区间 l,r,然后找能够按要求的出的最大值,

要求:对于l~r区间的数,取出一个数,然后其他数都加上取出的这个数的值,问最多能取出数的sum最大是多少。

思路:因为是01串,我们每次取最大的就能保证加的最大,稍微模拟一下就可以推出来

MAXsum=2^1的个数的-1+2^1的个数*2^0的个数

特判一下从头开始的:

//#pragma comment(linker, "/STACK:1024000000,1024000000") 
 
#include<stdio.h>
#include<string.h>  
#include<math.h>  
#include<stdlib.h>

//#include<map>   
//#include<set>
#include<deque>  
#include<queue>  
#include<stack>  
#include<bitset> 
#include<string>  
#include<fstream>  
#include<iostream>  
#include<algorithm>  
using namespace std;  
 
#define ll long long  
//#define max(a,b) (a)>(b)?(a):(b) 
//#define min(a,b) (a)<(b)?(a):(b) 
#define clean(a,b) memset(a,b,sizeof(a))// ˮӡ 
//std::ios::sync_with_stdio(false); 
const int MAXN=1e5+5; 
const ll INF=1e18;  
const ll mod=1e9+7;  

int arr[MAXN];
ll res[MAXN];

int main()
{
	std::ios::sync_with_stdio(false); 
	int n,q;
	string s;
	res[0]=1;
	for(int i=1;i<MAXN;++i)
		res[i]=(res[i-1]*2)%mod;//2的i次幂预处理出来
	while(cin>>n>>q)
	{
		cin>>s;
		int len=s.size();
		arr[0]=(s[0]=='1')?1:0;
		for(int i=1;i<len;++i)
			arr[i]=arr[i-1]+s[i]-'0';//获得1的个数
		int l,r;
		while(q--)
		{
			cin>>l>>r;
			l--,r--;
			if(l) //区间
			{
				ll x=res[arr[r]-arr[l-1]]-1;//
				ll y=res[r-l+1-(arr[r]-arr[l-1])];
				cout<<(x*y)%mod<<endl;	
			}
			else//从第一个开始
			{
				ll x=res[arr[r]]-1;//
				ll y=res[r-l+1-(arr[r])];
				cout<<(x*y)%mod<<endl;	
			}
		}
	}
}

D. Fun with Integers

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

好水的一道题啊!就是题目不好看懂,看懂之后就超简单!!

题目大意:给一个数n,然后找里面所有满足(2≤|a|,|b|≤n)的一对a和b,然后再找出x满足1<|x| 和 (a⋅x=b||b⋅x=a)

然后看样例,发现复数和正数是分开算的,于是对于每一对a,b都有四个答案,遍历一遍加起来即可:

int main()
{
	std::ios::sync_with_stdio(false); 
	int n;
	while(cin>>n)
	{
		ll ans=0;
		for(int i=2;i<=n;++i)
		{
			for(int j=2;j*i<=n;++j)
				ans+=j*4;
		}
		cout<<ans<<endl;
		
	}
}

猜你喜欢

转载自blog.csdn.net/qq_40482358/article/details/84202857