问题描述
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=1nai<=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;
}
全排列要会用,二分注意端点,先要判断是否要找规律,再是博弈的核心要抓住,树状数组等一些常规数据结构要灵活。