問題描述
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;
}
全排列要會用,二分注意端點,先要判斷是否要找規律,再是博弈的核心要抓住,樹狀數組等一些常規數據結構要靈活。