1. 程式人生 > >Codeforces Round #520 (Div. 2) A B C D

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;
		
	}
}