題目感覺比較模式,中規中矩,但是很容易超時或者是有些複雜情況覆蓋不到
進制轉換
題目描述
將一個長度最多爲30位數字的十進制非負整數轉換爲二進制數輸出。
輸入描述:
多組數據,每行爲一個長度不超過30位的十進制非負整數。
(注意是10進制數字的個數可能有30個,而非30bits的整數)
輸出描述:
每行輸出對應的二進制數。
示例1
輸入
複製
0
1
3
8
輸出
複製
0
1
11
1000
數字長度過長,long long 類型也無法存儲,使用字符串存儲
#include<iostream>
#include<stdio.h>
#include<string>
using namespace std;
string div2(string input){
// cout<<"div:"<<input<<endl;
int rmd=0;
int shang=0;
string res;
for(int i=0;i<input.size();i++){
shang=(rmd*10+input[i]-'0')/2;
res.push_back(shang+'0');
rmd=(rmd*10+input[i]-'0')%2;
}
while(res.size()>0){
if(res[0]=='0')
res.erase(res.begin());
else
break;
}
// cout<<"div2"<<endl;
if(res.size()==0){
return "0";
}
return res;
}
char rmd2(string input){
// cout<<"rmd:"<<input<<endl;
if((input[input.size()-1]-'0')%2==0){
return '0';
}
else{
return '1';
}
}
string getres(string input){
// cout<<"getres:"<<input<<endl;
string res;
char rmd;
while(input!="0"){
rmd=rmd2(input);
input=div2(input);
res.insert(res.begin(),rmd);
}
if(res.size()==0)
return "0";
return res;
}
int main(){
string input;
while(cin>>input){
cout<<getres(input)<<endl;
}
}
成績排序
查找和排序
題目:輸入任意(用戶,成績)序列,可以獲得成績從高到低或從低到高的排列,相同成績
都按先錄入排列在前的規則處理。
示例:
jack 70
peter 96
Tom 70
smith 67
從高到低 成績
peter 96
jack 70
Tom 70
smith 67
從低到高
smith 67
jack 70
Tom 70
peter 96
輸入描述:
輸入多行,先輸入要排序的人的個數,然後輸入排序方法0(降序)或者1(升序)再分別輸入他們的名字和成績,以一個空格隔開
輸出描述:
按照指定方式輸出名字和成績,名字和成績之間以一個空格隔開
示例1
輸入
複製
3
0
fang 90
yang 50
ning 70
輸出
複製
fang 90
ning 70
yang 50
排序,結構體定義,重載操作符,注意審題
#include<vector>
#include<algorithm>
using namespace std;
struct record{
string name;
int score;
int count;
int asc;
bool operator < (const record& r) const{
if(score!=r.score)
return score<r.score;
else{
if(asc==0)
return count>r.count;
else
return count<r.count;
}
}
};
int main(){
int n,asc;
int count;
while(cin>>n){
count=0;
cin>>asc;
vector<record> re;
while(n--){
record temp;
cin>>temp.name;
cin>>temp.score;
temp.count=count;
temp.asc=asc;
re.push_back(temp);
count++;
}
sort(re.begin(),re.begin()+re.size());
if(asc==1){
for(int i=0;i<re.size();i++){
cout<<re[i].name<<" "<<re[i].score<<endl;
}
}
else if(asc==0){
for(int i=re.size()-1;i>=0;i--){
cout<<re[i].name<<" "<<re[i].score<<endl;
}
}
}
}
約數的個數
輸入n個整數,依次輸出每個數的約數的個數
輸入描述:
輸入的第一行爲N,即數組的個數(N<=1000)
接下來的1行包括N個整數,其中每個數的範圍爲(1<=Num<=1000000000)
當N=0時輸入結束。
輸出描述:
可能有多組輸入數據,對於每組輸入數據,
輸出N行,其中每一行對應上面的一個數的約數的個數。
示例1
輸入
複製
5
1 3 4 6 12
輸出
複製
1
2
3
4
6
數的範圍很大,直接暴力會超時,轉化爲開方
#include<iostream>
using namespace std;
int main(){
int n;
int tmp;
while(cin>>n){
while(n--){
cin>>tmp;
int sum=0;
int i;
for(i=1;i*i<tmp;i++){
if(tmp%i==0)
sum+=2;
}
if(i*i==tmp)
sum++;
cout<<sum<<endl;
}
}
}
代理服務器
題目描述
使用代理服務器能夠在一定程度上隱藏客戶端信息,從而保護用戶在互聯網上的隱私。我們知道n個代理服務器的IP地址,現在要用它們去訪問m個服務器。這 m 個服務器的 IP 地址和訪問順序也已經給出。系統在同一時刻只能使用一個代理服務器,並要求不能用代理服務器去訪問和它 IP地址相同的服務器(不然客戶端信息很有可能就會被泄露)。在這樣的條件下,找到一種使用代理服務器的方案,使得代理服務器切換的次數儘可能得少。
輸入描述:
每個測試數據包括 n + m + 2 行。
第 1 行只包含一個整數 n,表示代理服務器的個數。
第 2行至第n + 1行每行是一個字符串,表示代理服務器的 IP地址。這n個 IP地址兩兩不相同。
第 n + 2 行只包含一個整數 m,表示要訪問的服務器的個數。
第 n + 3 行至第 n + m + 2 行每行是一個字符串,表示要訪問的服務器的 IP 地址,按照訪問的順序給出。
每個字符串都是合法的IP地址,形式爲“xxx.yyy.zzz.www”,其中任何一部分均是0–255之間的整數。輸入數據的任何一行都不包含空格字符。
其中,1<=n<=1000,1<=m<=5000。
輸出描述:
可能有多組測試數據,對於每組輸入數據, 輸出數據只有一行,包含一個整數s,表示按照要求訪問服務器的過程中切換代理服務器的最少次數。第一次使用的代理服務器不計入切換次數中。若沒有符合要求的安排方式,則輸出-1。
示例1
輸入
複製
3
166.111.4.100
162.105.131.113
202.112.128.69
6
72.14.235.104
166.111.4.100
207.46.19.190
202.112.128.69
162.105.131.113
118.214.226.52
輸出
複製
1
動態規劃思想
#include<iostream>
#include<vector>
using namespace std;
int main(){
int n;
int MAX=6000;
while(cin>>n){
vector<string> agent(n);
for(int i=0;i<n;i++){
cin>>agent[i];
}
int m;
cin>>m;
vector<string> server(m);
for(int i=0;i<m;i++){
cin>>server[i];
}
vector<vector<int> > dis(m+1);
for(int i=0;i<m+1;i++){
dis[i].resize(n);
for(int j=0;j<n;j++){
dis[i][j]=MAX;
}
}
for(int i=m-1;i>=0;i--){
for(int j=0;j<n;j++){
if(server[i]==agent[j]){
dis[i][j]=0;
}
else{
dis[i][j]=dis[i+1][j]+1;
}
}
}
int count=0;
int index=0;
int jndex=0;
int max=0;
for(int i=0;i<n;i++){
if(max<dis[0][i]){
index=i;
max=dis[0][i];
}
}
if(max==0){
cout<<"-1"<<endl;
break;
}
jndex=jndex+dis[0][index];
while(jndex<m){
max=0;
index=0;
for(int i=0;i<n;i++){
if(max<dis[jndex][i]){
index=i;
max=dis[jndex][i];
}
}
if(max==0){
count=-1;
break;
}
jndex=jndex+dis[jndex][index];
count++;
}
cout<<count<<endl;
}
}
手機鍵盤
題目描述
按照手機鍵盤輸入字母的方式,計算所花費的時間 如:a,b,c都在“1”鍵上,輸入a只需要按一次,輸入c需要連續按三次。 如果連續兩個字符不在同一個按鍵上,則可直接按,如:ad需要按兩下,kz需要按6下 如果連續兩字符在同一個按鍵上,則兩個按鍵之間需要等一段時間,如ac,在按了a之後,需要等一會兒才能按c。 現在假設每按一次需要花費一個時間段,等待時間需要花費兩個時間段。 現在給出一串字符,需要計算出它所需要花費的時間。
輸入描述:
一個長度不大於100的字符串,其中只有手機按鍵上有的小寫字母
輸出描述:
輸入可能包括多組數據,對於每組數據,輸出按出Input所給字符串所需要的時間
示例1
輸入
複製
bob
www
輸出
複製
7
7
能記起九宮格是什麼樣就行了
#include<iostream>
#include<vector>
using namespace std;
int main(){
vector<int>pos(26);
vector<int>time(26);
pos[0]=2;
time[0]=1;
pos[1]=2;
time[1]=2;
pos[2]=2;
time[2]=3;
pos[3]=3;
time[3]=1;
pos[4]=3;
time[4]=2;
pos[5]=3;
time[5]=3;
pos[6]=4;
time[6]=1;
pos[7]=4;
time[7]=2;
pos[8]=4;
time[8]=3;
pos[9]=5;
time[9]=1;
pos[10]=5;
time[10]=2;
pos[11]=5;
time[11]=3;
pos[12]=6;
time[12]=1;
pos[13]=6;
time[13]=2;
pos[14]=6;
time[14]=3;
pos[15]=7;
time[15]=1;
pos[16]=7;
time[16]=2;
pos[17]=7;
time[17]=3;
pos[18]=7;
time[18]=4;
pos[19]=8;
time[19]=1;
pos[20]=8;
time[20]=2;
pos[21]=8;
time[21]=3;
pos[22]=9;
time[22]=1;
pos[23]=9;
time[23]=2;
pos[24]=9;
time[24]=3;
pos[25]=9;
time[25]=4;
string s;
while(cin>>s){
int res=0;
int pre=-1;
for(int i=0;i<s.size();i++){
int ii=s[i]-'a';
res+=time[ii];
if(pos[ii]==pre) res+=2;
pre=pos[ii];
}
cout<<res<<endl;
}
}
整數拆分1
題目描述
一個整數總可以拆分爲2的冪的和,例如: 7=1+2+4 7=1+2+2+2 7=1+1+1+4 7=1+1+1+2+2 7=1+1+1+1+1+2 7=1+1+1+1+1+1+1 總共有六種不同的拆分方式。 再比如:4可以拆分成:4 = 4,4 = 1 + 1 + 1 + 1,4 = 2 + 2,4=1+1+2。 用f(n)表示n的不同拆分的種數,例如f(7)=6. 要求編寫程序,讀入n(不超過1000000),輸出f(n)%1000000000。
輸入描述:
每組輸入包括一個整數:N(1<=N<=1000000)。
輸出描述:
對於每組數據,輸出f(n)%1000000000。
示例1
輸入
複製
7
輸出
複製
6
題目的意思是將整數n拆分成2的冪,一共有多少種拆分方法,思路爲動態規劃,那麼關鍵就是遞歸方程如何寫!!
考慮以下情況
- n爲奇數時,可以拆分的情況之後在n-1的拆分情況上加1,即 f(n)=f(n-1)
- n爲偶數時,對n進行拆分,按照可不可以拆分出1劃分
- 可以拆分出1,f(n-1)
- 不可以拆分出1,也就是將n/2拆分的結果每個乘2,即f(n/2)
- f(n)=f(n-1)+f(n/2)
- 起始爲 f(0)=0,f(1)=1,f(2)=2
#include<stdio.h>
int main(){
int dp[1000001],num,i;
dp[0]=0;
dp[1]=1;
dp[2]=2;
for(i=3;i<=1000000;i++){
dp[i]=0;
if(i&1)
dp[i]=(dp[i-1])%1000000000;
else
dp[i]=(dp[i-1]+dp[i/2])%1000000000;
}
while(scanf("%d",&num)!=EOF)
printf("%d\n",dp[num]);
}
關於數組分配的空間是不是太大這個問題很玄學
數字拆分2
這道題爲看到的另一個經典的動態規劃題目
輸入n,k;輸出將n拆分爲最大值爲k的組合的個數
如n=5,k=5時輸出結果爲5
思路如下
- 當n=k時,f(n,k)=f(n,k-1)+1。加的1時n=k
- 當n<k時,f(n,k)=f(n,n)
- 當n>k時,考慮能不能拆分出k
- f(n,k)=f(n-k,k)+f(n,k-1)
- 初始條件爲 f(1,i)=1,f(i,1)=1
#include<stdio.h>
#include<iostream>
#include<vector>
using namespace std;
int main(){
int n,k;
while(cin>>n){
cin>>k;
vector<vector <int> > dp(n+1);
for(int i=0;i<=n;i++){
dp[i].resize(k+1);
for(int j=0;j<=k;j++){
dp[i][j]=0;
if(j==1) dp[i][j]=1;
if(i==1) dp[i][j]=1;
}
}
for(int i=2;i<=n;i++){
for(int j=2;j<=k;j++){
if(i==j) dp[i][j]=dp[i][j-1]+1;
else if(i<j) dp[i][j]=dp[i][i];
else{
dp[i][j]=dp[i-j][j]+dp[i][j-1];
}
}
}
}
}