题目

问题描述

  Excel单元格的地址表示很有趣,它使用字母来表示列号。
  比如,
  A表示第1列,
  B表示第2列,
  Z表示第26列,
  AA表示第27列,
  AB表示第28列,
  BA表示第53列,
  ....


  当然Excel的最大列号是有限度的,所以转换起来不难。
  如果我们想把这种表示法一般化,可以把很大的数字转换为很长的字母序列呢?


  本题目即是要求对输入的数字, 输出其对应的Excel地址表示方式。

样例输入

26

样例输出

Z

样例输入

2054

样例输出

BZZ

数据规模和约定

  我们约定,输入的整数范围[1,2147483647]


  峰值内存消耗(含虚拟机) < 256M
  CPU消耗 < 1000ms




  请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。


  注意:
  main函数需要返回0;
  只使用ANSI C/ANSI C++ 标准;
  不要调用依赖于编译环境或操作系统的特殊函数。
  所有依赖的函数必须明确地在源文件中 #include <xxx>
  不能通过工程设置而省略常用头文件。


  提交程序时,注意选择所期望的语言类型和编译器类型。


  ------------------------------


  笨笨有话说:
  这有点像进制关系,又不完全是。好像末2位是以1当26,末3位是以1当26*26


  歪歪有话说:
  要是从字母序列转数字还好点,倒过来有点麻烦,不过计算机跑得快啊。

#include<bits/stdc++.h>
using namespace std;  
#define ll long long
int b[1000000];
int main(){
	ll a ;
	cin>>a;int i=0;
	while(a){
		
		int yushu=a%26;//consider in aspects of yuanli
		if(yushu==0) yushu=26;
		a=(a-yushu)/26;
		b[i++]=yushu;
	}
	for(int j=i-1;j>=0;j--){
		cout<<char(b[j]+'A'-1);
	}
	return 0;
}

emmm.好久没发博客了,从原理出发,别靠感觉乱写。

问题描述

  儿童节那天有K位小朋友到小明家做客。小明拿出了珍藏的巧克力招待小朋友们。
  小明一共有N块巧克力,其中第i块是Hi x Wi的方格组成的长方形。


  为了公平起见,小明需要从这 N 块巧克力中切出K块巧克力分给小朋友们。切出的巧克力需要满足:


  1. 形状是正方形,边长是整数
  2. 大小相同


  例如一块6x5的巧克力可以切出6块2x2的巧克力或者2块3x3的巧克力。


  当然小朋友们都希望得到的巧克力尽可能大,你能帮小Hi计算出最大的边长是多少么?

输入格式

  第一行包含两个整数N和K。(1 <= N, K <= 100000)
  以下N行每行包含两个整数Hi和Wi。(1 <= Hi, Wi <= 100000)
  输入保证每位小朋友至少能获得一块1x1的巧克力。

输出格式

  输出切出的正方形巧克力最大可能的边长。

样例输入

2 10
6 5
5 6

样例输出

2

数据规模和约定

  峰值内存消耗(含虚拟机) < 256M
  CPU消耗 < 1000ms

 

#include<bits/stdc++.h>
using namespace std;
int x,y;
struct node{//错误代码,靠直觉写的,看来直觉不可信,因为巧克力不可以拼在一起 
	int a,b;
}nod[100002];
bool cmp(node x,node y){
	return x.a<y.a;
}
bool check(int u){
	int res=nod[x].b-nod[u-1].b;
	if(res/nod[u].a>=y){
		return true;
	}
	else return false;
}
int main(){

	cin>>x>>y;
	for(int i=1;i<=x;i++){
		int o,p;
		cin>>o>>p;
		nod[i].a=min(o,p);
		nod[i].b=max(o,p);
	}
	for(int i=2;i<=x;i++){
		nod[i].b=nod[i].b+nod[i-1].b;
	}
	
	sort(nod+1,nod+x+1,cmp);
	int l=1,r=x;
	int mid;
	while(l<r){
		mid=(l+r)/2;
		if(check(mid)){
			l=mid;
		}
		else {
			r=mid-1;
		}
		
	}
	cout<<nod[mid].a;
	return 0;
}
#include<bits/stdc++.h>
using namespace std;
int h[100010];
int w[100010];int x,y;
bool check(int n){
	int res=0;
	for(int i=1;i<=x;i++){
		int x1=h[i]/n;
		int y2=w[i]/n;
		res+=x1*y2;
		
	} 
//	cout<<endl<<res<<"fe"<<n<<endl;
	if(res>=y) return true;
	else return false;
}
int main(){

	cin>>x>>y;int shu=0;
	for(int i=1;i<=x;i++){
		cin>>h[i]>>w[i];
		shu=max(shu,h[i]);
	}
//	cout<<shu<<endl;
	int l=1,r=shu+1;//为了取到shu 
	int mid;
	while(l<(r-1)){
	//	cout<<l<<" "<<r<<endl;
		mid=(l+r)/2;
	//	cout<<mid<<endl;
		if(check(mid)){
			l=mid;
		}
		else r=mid;
	}
	cout<<l<<endl;
	return 0;
} 

emmm,写的飞快,但是错的一堆。

问题描述

  小明正在整理一批历史文献。这些历史文献中出现了很多日期。小明知道这些日期都在1960年1月1日至2059年12月31日。令小明头疼的是,这些日期采用的格式非常不统一,有采用年/月/日的,有采用月/日/年的,还有采用日/月/年的。更加麻烦的是,年份也都省略了前两位,使得文献上的一个日期,存在很多可能的日期与其对应。


  比如02/03/04,可能是2002年03月04日、2004年02月03日或2004年03月02日。


  给出一个文献上的日期,你能帮助小明判断有哪些可能的日期对其对应吗?

输入格式

  一个日期,格式是"AA/BB/CC"。 (0 <= A, B, C <= 9)

输出格式

  输出若干个不相同的日期,每个日期一行,格式是"yyyy-MM-dd"。多个日期按从早到晚排列。

样例输入

02/03/04

样例输出

2002-03-04
2004-02-03
2004-03-02

#include<bits/stdc++.h>
using namespace std;
set<string>e;
int a[2][13]={ 0,31,28,31,30,31,30,31,31,30,31,30,31,
0,31,29,31,30,31,30,31,31,30,31,30,31
				
};
void check(int y,int m,int d){
//	cout<<y<<" "<<m<<" "<<d<<endl;
	y+=1900;int f=0;string s;char c[15];
	if(y<1960) y+=100;//
	if(y%400==0||(y%100!=0&&y%4==0)) f=1;
	if(m>=1&&m<=12){
		if(d>=1&&d<=a[f][m]){
			sprintf(c,"%d-%02d-%02d",y,m,d);
			if(e.count(s=c)==0){
				e.insert(s);
			}
		}
		
	}
	
}
int main(){
	int a1,a2,a3;
	scanf("%2d/%2d/%2d",&a1,&a2,&a3);//格式控制要会灵活使用 
//	cout<<a1<<"fe"<<a2<<"fe"<<a3<<endl;
	check(a1,a2,a3);
	check(a3,a1,a2);
	check(a3,a2,a1);
	for(set<string>::iterator it=e.begin();it!=e.end();it++){//审题很重要 
		cout<<*it<<endl;//集合自己便会排序 
	} 
	return 0;
} 

Alice and Bob

Description

 

AliceAlice和BobBob在一棵有根树上移动棋子,每次将棋子向所在点的其中一个儿子移动

不能移动就算失败,AliceAlice先手,BobBob后手,两人均采取最优策略,最后的赢家是谁

Input

 

输入第一行为一个整数nn,表示有根树的节点数目(1 \le n \le 100000)(1≤n≤100000)

接下来n-1n−1行,每行两个数字u,vu,v,表示点uu和点vv之间存在一条边

接下来一行为一个整数mm,表示询问次数(1 \le m \le 10)(1≤m≤10)

接下来mm行,每行只有一个整数xx,表示本次询问的树的根节点的标号(1 \le x \le n)(1≤x≤n)

(多次询问时,只是根节点有变化,树的边是不变的)

Output

 

对于每次询问,输出一行,如果是先手胜,输出"Alice",否则输出"Bob"(不含引号)

Sample Input 1 

3
1 2
2 3
1
1

Sample Output 1

Bob

Sample Input 2 

5
1 2
1 3
3 4
4 5
2
2
4

Sample Output 2

Bob
Alice

Source

牛客小白赛2

#include<bits/stdc++.h>
using namespace std;
bool vis[100010];
vector<int >gg[100010];//不熟练 
bool win[100010];
bool dfs(int a){
	vis[a]=1;int son=0;int win_son=0;
	for(int i=0;i<gg[a].size();i++){
		int u=gg[a][i];
		if(vis[u]) continue;
		son++;
		if(dfs(u)) win_son++;
		
	}
	if(son==win_son) win[a]=0;
	else win[a]=1;
	return win[a];
}
int main(){
	int n;int u,v;
	cin>>n;
	for(int i=1;i<n;i++){
		cin>>u>>v;
		gg[u].push_back(v);
		gg[v].push_back(u);
		
	}
	int m;
	cin>>m;
	while(m--){
		int q;
		memset(vis,0,sizeof(vis));
		
		cin>>q;
		if(dfs(q))
		cout<<"Alice\n";
		else cout<<"Bob"<<endl;
		
	}
	return 0;
	
}

Max answer

Description

 

给出一个长度为nn的数字序列aa,将其任意排序,使得\sum_{i = 1}^{n}|a_{i\%n+1} - a_{i}|∑i=1n​∣ai%n+1​−ai​∣最大

Input

 

第一行一个整数TT,表示有TT组数据(1 \le T \le 10)(1≤T≤10)

对于每组数据,输入第一行只有一个整数n(1 \le n \le 100000)n(1≤n≤100000)

第二行输入nn个整数表示ai(-(10^9+7) \le ai \le 10^9+7)ai(−(109+7)≤ai≤109+7)

Output

 

对于每一组数据,输出"Case x: ans"(不含引号)

xx表示第xx组数据,从11开始编号,ansans表示答案

Sample Input 1 

2
5
7 3 15 12 8
7
-2 0 8 9 -5 3 10

Sample Output 1

Case 1: 34
Case 2: 68

Source

牛客小白赛2

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int a[100010];
int b[100010];
int main(){
	int t;
	cin>>t;int ccase=0;
	while(t--){
		int n;scanf("%d",&n);int sum=0;
		for(int i=1;i<=n;i++){
			scanf("%d",&a[i]);
		}
		sort(a+1,a+n+1);
		int i,j,k;
		//cout<<"fefe";
		for(i=n,j=1,k=1;i>j;i--,j++){
			b[k++]=a[i];
			b[k++]=a[j];
			//cout<<"fef";
		}
		//cout<<k<<endl;
		//cout<<"fefefef";
	//	for(int i=1;i<k;i++)
	//		cout<<b[i]<<" ";
		if(i==j) b[k++]=a[j];ll res=0;
		b[0]=b[k-1];
		for(int q=1;q<k;q++)
		{
			res+=abs(b[q]-b[q-1]);
		}
		cout<<"Case "<<++ccase<<": ";
		cout<<res<<endl;
		
	
/*	if(n%2==1) 
{
		for(int i=1;i<=n/2;i++){
		sum-=a[i]*2;
	}
	for(int i=(n/2)+1;i<=n;i++){
		sum+=a[i];
	}
	cout<<sum<<endl;
}*/
}
return 0;
	
}

反转

Description

 

有一个nn个元素的数组,每个元素初始均为00

有mm条操作指令,操作一:将[l,r][l,r]区间内的数字进行反转(00变成11,11变成00)

操作二:询问第ii个元素的值

Input

 

输入第一行包含两个整数n,mn,m,表示数组的长度和指令的条数

接下来mm行,每行第一个数tt表示操作的种类:

  • 若t=1t=1,则接下来有两个数l,rl,r,表示区间[l,r][l,r]的每个数均反转
  • 若t=2t=2,则接下来只有一个数ii,表示询问的下标。

(1\le n \le 10^5, 1 \le m \le 5*10^5,l \le r)(1≤n≤105,1≤m≤5∗105,l≤r)

Output

 

每个操作二输出一行,表示每次操作二的回答

Sample Input 1 

20 10
1 1 10
2 6
2 12
1 5 12
2 6
2 15
1 6 16
1 11 17
2 12
2 6

Sample Output 1

1
0
0
0
1
1

Source

LOJ-10117

#include<bits/stdc++.h>
using namespace std;
int a[100010];
int n;
int que(int q){
	int res=0;
	for(int i=q;i;i-=i&-i){
		res+=a[i];
	}
	return res;
}
void insert(int x,int y){
	for(int i=x;i<=n;i+=i&-i){
		a[i]+=y;
	}
	return ;
}
int main (){
	int m;
	cin>>n>>m;//那就说明要树状数组减少复杂度, 
	while(m--){
		int q,num;
		cin>>q>>num;
		if(q==1){
			int r;cin>>r;int shu;
			insert(num,1);
			insert(r+1,-1);//不包含端点 
			
		}
		else {
			
			cout<<(que(num)&1)<<endl; // 
			
		}
	
	}
	return 0;
}

数列分段

Description

 

给定长度为nn的正整数数列aa,将其分成mm段,要求每段连续,且每段的和的最大值最小

例如数列4\ 2\ 4\ 5\ 14 2 4 5 1要分成33段

若分成[4\ 2][4\ 5][1][4 2][4 5][1],每段和分别为6,9,16,9,1,和的最大值为99

若分成[4][2\ 4][5\ 1][4][2 4][5 1],每段和分别为4,6,64,6,6,和的最大值为66

并且无论如何分段,最大值不会小于66,所以答案为66。

Input

 

输入第一行包含两个整数n,m(1 \le M \le N \le 10^5)n,m(1≤M≤N≤105)

第二行包含nn个整数表示给定的正整数数列ai(1 \le ai \le 10^9\ \ \sum_{i = 1}^{n}ai <= 10^9)ai(1≤ai≤109  ∑i=1n​ai<=109)

Output

 

输出仅包含一个整数表示每段和最大值最小为多少

Sample Input 1 

5 3
4 2 4 5 1

Sample Output 1

6

Source

LOJ-10014

#include<bits/stdc++.h>
using namespace std;
int a[100010];
int n;int m;
#define ll long long
int check(int shu){
	int summ=0;int q=1;//bool flag=false;
	for(int i=1;i<=n;i++){
		if(summ+a[i]<=shu){//条件写错了 
			summ+=a[i];
		//	cout<<summ<<endl;
			
		}
		else {
			//flag=true;
			q++;
			summ=a[i];
		//	cout<<"fe"<<endl;
			
		}
		
		
	}
	return q;
	
}
int main(){

	cin>>n>>m;int sum=0;int maxxx=0;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		sum+=a[i];
		maxxx=max(maxxx,a[i]);
	}
	int r=(sum-m+1);//这些都无所谓 
	maxxx=max(maxxx,(sum+m-1)/m);//该选择最大的元素为最小,而我找了平均。 
	//cout<<sum<<endl;
	
	//r=sum;
	int l=maxxx;
	int mid;
	while(l<r){
		mid=(l+r)/2;
		if(check(mid)<=m)
		r=mid;//我错了 ,这个中间的总是忽略 
		else 
		l=mid+1;
	}
	cout<<l<<endl;
	return 0;
	
}

带分数

Description

 

100100可以表示成带分数的形式:100 = 3\frac{69258}{714}100=371469258​

还可以表示成:100 = 82\frac{3546}{197}100=821973546​

注意:带分数中,数字1-91−9分别出现且只出现一次(不包括00)

类似这样的带分数,100100有1111种表示法

那么数字nn有多少种表示法呢

Input

 

第一行一个整数TT,表示有TT组数据(1 \le T \le 10)(1≤T≤10)

对于每组数据,输入只有一个整数n(1 \le n \le 100000)n(1≤n≤100000)

Output

 

对于每一组数据,输出"Case x: ans"(不含引号)

xx表示第xx组数据,从11开始编号,ansans表示答案

Sample Input 1 

3
100
105
37

Sample Output 1

Case 1: 11
Case 2: 6
Case 3: 6

Source

蓝桥杯

#include<bits/stdc++.h>
using namespace std;
int b[10];
int a[10];
int main(){
	int t;
	cin>>t;
	b[0]=1;
	for(int i=1;i<=9;i++){
		b[i]=b[i-1]*10;
	}
	int ccase=0;
 	while(t--){
		int n;
		cin>>n;int ans=0;
		
		for(int i=1;i<=9;i++)
		a[i]=i;
		do{
			int num=0;
			for(int i=1;i<=9;i++){
				num=num*10+a[i];
			}
			for(int i=1;i<=7;i++){
				int num1=num/b[9-i];
				int num2=num%b[9-i];
				if(num1>n) break;
				for(int j=i+1,k=1;j<=9;j++,k++){
					int fir=num2/b[k];
					int sec=num2%b[k];
					if(fir<sec) break;
					if(fir%sec==0&&num1+fir/sec==n){
						ans++;
					}
				}
				
			}
		}while(next_permutation(a+1,a+10)) ;
		cout<<"Case "<<++ccase<<": ";
		cout<<ans<<endl;
	}
	return 0;
}

全排列要会用,二分注意端点,先要判断是否要找规律,再是博弈的核心要抓住,树状数组等一些常规数据结构要灵活。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值