NOIP 提高組 初賽 四、閱讀程序寫結果 習題集(八)NOIP2012-NOIP2013
1.第十八屆(NOIP2012)
問題:
1.
//2012.4.1
#include <stdio.h>
int main(){
int n,i,temp,sum;
int a[100];
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
for(i=1;i<=n-1;i++)
if(a[i]>a[i+1]){
temp=a[i];
a[i]=a[i+1];
a[i+1]=temp;
}
for(i=n;i>=2;i--)
if(a[i]<a[i-1]){
temp=a[i];
a[i]=a[i-1];
a[i-1]=temp;
}
sum=0;
for(i=2;i<=n-1;i++)
sum+=a[i];
printf("%d\n",sum/(n-2));
return 0;
}
//輸入:8
//40 70 50 70 20 40 10 30
2.
//2012.4.2
#include <stdio.h>
int gcd(int a,int b){
if(a%b==0)
return b;//網上流傳的pascal有些此處return 0;
else
return gcd(b,a%b);
}
int main(){
int n,i,ans;
scanf("%d",&n);
ans=0;
for(i=1;i<=n;i++)
if(gcd(n,i)==i)
ans++;
printf("%d\n",ans);
return 0;
}
//輸入:120
3.
//2012.4.3
#include <stdio.h>
const int size=20;
int data[20];
int n,i,h,ans;
void merge(){
data[h-1]+=data[h];
h--;
ans++;
}
int main(){
scanf("%d",&n);
h=1;
data[h]=1;
ans=0;
for(i=2;i<=n;i++){
h++;
data[h]=1;
while(h>1&&data[h]==data[h-1])
merge();
}
printf("%d\n",ans);
return 0;
}
//(1)
//輸入:8
//(2)
//輸入:2012
4.
//2012.4.4
#include <stdio.h>
#include <string.h>
int left[20],right[20],father[20];
char s1[20],s2[20],s3[20];
int n,ans,tmpLen;
void check(int x){//本題pascal寫法與C差異較大,且有些錯誤
if(left[x]>=0)
check(left[x]);
tmpLen=strlen(s3);
s3[tmpLen]=s1[x];
s3[tmpLen+1]='\0';
if(right[x]>=0)
check(right[x]);
}
void calc(int x,int dep){
ans=ans+dep*(s1[x]-'A'+1);
if(left[x]>=0)
calc(left[x],dep+1);
if(right[x]>=0)
calc(right[x],dep+1);
}
void dfs(int x,int th){
if(th==n){
s3[0]='\0';
check(0);
if(strcmp(s2,s3)==0){
ans=0;
calc(0,1);
printf("%d\n",ans);
}
return;
}
if(left[x]==-1&&right[x]==-1){
left[x]=th;
father[th]=x;
dfs(th,th+1);
father[th]=-1;
left[x]=-1;
}
if(right[x]==-1){
right[x]=th;
father[th]=x;
dfs(th,th+1);
father[th]=-1;
right[x]=-1;
}
if(father[x]>=0)
dfs(father[x],th);
}
int main(){
scanf("%s",s1);
scanf("%s",s2);
n=strlen(s1);
memset(left,-1,sizeof(left));
memset(right,-1,sizeof(right));
memset(father,-1,sizeof(father));
dfs(0,1);
return 0;
}
//輸入:ABCDEF
//BCAEDF
問題解答:
1.就算不熟悉冒泡排序,此題也挺簡單,直接模擬,過程如下:
看起來數據量挺大,但寫起來挺快,最多5分鐘,肯定好了,
答案:41
1簡單
2.作了模擬,如圖所示:
發現該程序意圖是統計n與i能整除的數量。
能被120整除的數:1,2,3,4,5,6,8,10,12,15,20,24,30,40,60,120共計16個。
答案:16
該題一不小心,就容易漏數。
2中等
想到一個好辦法:
120/1=120,120/2=60,120/3=40,120/4=30,120/5=24,120/6=20,120/8=15,120/10=12.
此種辦法,一個不漏,
1,120,2,60,3,40,4,30,5,24,6,20,8,15,10,12.一共16個。
2簡單
3.輸入8思考過程如下:
答案:7
難度中等,能將輸入8做對,水平已經不錯,證明具有相當的跟蹤程序的水平。此題難在while()而不是if()。
輸入2012
參考:https://zhidao.baidu.com/question/580345391.html
n值 數組有效元素(包括轉換前和轉換後)
i=2 1,1->2
i=3 2,1
i=4 2,1,1->2,2->4
i=5 4,1
i=6 4,1,1->4,2
i=7 4,2,1
i=8 4,2,1,1->4,2,2->4,4->8
至此次轉換次數(->)爲7次,即ans=7
i=9 8,1
i=10 8,1,1->8,2
i=11 8,2,1
i=12 8,2,1,1->8,2,2->8,4
i=13 8,4,1
i=14 8,4,1,1->8,4,2
i=15 8,4,2,1
i=16 8,4,2,1,1->8,4,2,2->8,4,4->8,8->16
由上可知,數組有效元素的和爲n,當n可以表示爲2(x)時,轉換次數爲2(0)+2(1)+2(2)+2(3)+...+2(x-1)
當i從1變到1024時,轉換次數爲2(0)+...+2(9)=1023
當i從1變到2048時,轉換次數爲2(0)+...+2(10)=2047,但是i變不到2048,只變到2012(n的值)
所以,最終數組的有效元素是:
i=2012 1024,512,256,128,64,16,8,4 //有效數組元素的和爲2012(此處不清楚,還需消化)
所以,當n=2012時,最終的結果是:
t(1024)+t(512)+t(256)+t(128)+t(64)+t(16)+t(8)+t(4) //t(x)表示從數組初始狀態變到x狀態
=1023+511+255+127+63+15+7+3=2004
答案:2004
此處難度:難 考試中先跳過。
4.程序跟得暈乎乎的,暫時擱置,等實力強勁時再來。
答案:55
1.第十九屆(NOIP2013)
問題:
1.
//2013.4.1
#include <stdio.h>
#include <string.h>
const int SIZE=100;
int main(){
int i,n;
char str[SIZE];
int isPlalindrome;
scanf("%s",str);
n=strlen(str);
isPlalindrome=1;
for(i=0;i<n/2;i++){
if(str[i]!=str[n-i-1])
isPlalindrome=0;
}
if(isPlalindrome)
printf("Yes\n");
else
printf("No\n");
}
//輸入:abceecba
2.
//2013.4.2
#include <stdio.h>
int main(){
int a,b,u,v,i,num;
scanf("%d%d%d%d",&a,&b,&u,&v);
num=0;
for(i=a;i<=b;i++){
if(i%u==0||i%v==0)
num++;
}
printf("%d\n",num);
return 0;
}
//輸入:1 1000 10 15
3.
//2013.4.3
#include <stdio.h>
const int SIZE=100;
int main(){
int n,ans,i,j;
int height[SIZE],num[SIZE];
scanf("%d",&n);
for(i=0;i<n;i++){
scanf("%d",&height[i]);
num[i]=1;
for(j=0;j<i;j++)
if(height[j]<height[i]&&num[j]>=num[i])
num[i]=num[j]+1;
}
ans=0;
for(i=0;i<n;i++)
if(num[i]>ans)
ans=num[i];
printf("%d\n",ans);
return 0;
}
//輸入:8
// 3 2 5 11 12 7 4 10
4.
//2013.4.4
#include <stdio.h>
#include <string.h>
const int SIZE=100;
int n,m,p,count;
int a[SIZE][SIZE];
void colour(int x,int y){
count++;
a[x][y]=1;
if(x>1&&a[x-1][y]==0)
colour(x-1,y);
if(y>1&&a[x][y-1]==0)
colour(x,y-1);
if(x<n&&a[x+1][y]==0)
colour(x+1,y);
if(y<m&&a[x][y+1]==0)
colour(x,y+1);
}
int main(){
int ans,x,y,i,j;
memset(a,0,sizeof(a));
scanf("%d%d%d",&n,&m,&p);
for(i=1;i<=p;i++){
scanf("%d%d",&x,&y);
a[x][y]=1;
}
ans=0;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
if(a[i][j]==0){
count=0;
colour(i,j);
if(ans<count)
ans=count;
}
printf("%d\n",ans);
return 0;
}
//輸入:
/*
6 5 9
1 4
2 3
2 4
3 2
4 1
4 3
4 5
5 4
6 4
*/
問題解答:
1.思考過程如圖所示:
直接跟蹤程序,此題兩三分鐘即可做好。
答案:Yes
1簡單
2.思考過程如圖所示:
答案:133
耗時:兩三分鐘
3.思考過程如圖所思:
num[i]>ans這段代碼是在num中找最大的數。
很快能得出答案:4
耗時:5分鐘
3中等
4.思考過程如圖所示:
跟蹤程序,發現colour函數核心處理部分,如圖所示:
很快發現該函數是統計同一區域0的個數。
該程序意圖明瞭:統計同一區域0的個數,找出最多0的個數。
答案:7
耗時:5分鐘
4中等
2016-12-31 12:04