1.[NOIP1998]分割单词
/*
完善程序题 普及篇 1.[NOIP1998]分割单词
四、根据题意,补充完善以下程序:(14%)
输入一长度不超过80个字符的字符串(称为源串),
该字符串由小写英文字母、空格组成,并以'.'结束。
单词是由连续字母组成,两个单词之间至少有一个空格。
本程序的功能为:首先找出字符串中所有单词并保留一个空格作为单词分隔,
存入数组ch中。然后用键盘输入一个待查找的单词,
以字符'$'结束。采用顺序查找的方法在ch中进行查找,若找到,
则输出该单词在ch中出现的序号(若有多个位置出现该单词,则只输出第一个序号位置)。
若不存在,则输出'NOT FOUND'。
程序如下:(14%)
*/
#include <iostream>
#include <cstdio>
using namespace std;
char a[85],b[85],ch[85];
int i,j,k,n,m;
int main( )
{
n=0;
do
{
__(1)___;a[n]=getchar();
}while(a[n]!='.');
k=0;
for(i=1;i<=n;++i)
if(a[i]>='a'&& a[i]<='z')
{
k++;
___(2)___;
}else if(k!=0)
if(ch[k]!='')
{
k++;ch[k]='';
}
m=0;___(3)___;
do
{
m++;b[m]=getchar();
}while( __(4)__);
i=1;j=1;k=1;b[m]='';
while(i<=n && j<=m)
{
if( __(5)__ )
{
i++;j++;
}
else
{
while( ch[i]!='') i=i+1;
i=i+1;j=1;k++;
}
}
if( __ (6)___ )
{
printf("%d",k);
}
else printf("NOT FOUND");
return 0;
}
/*
答案:
(1)、n=n+1
(2)、ch[k]=a[i]
(3)、n=k
(4)、b[m]!='$'
(5)、 ch[i]==b[j]
(6)、j>m-1
*/
完善程序题 普及篇 2、【NOIP1998】FBZ串问题
3.[NOIP1999]全排列
/*
完善程序题 普及篇 3.[NOIP1999]全排列
[问题描述]
用生成法求出1,2,…,r的全排列(r<=8)
[程序说明]
用数组:a[r+1]表示排列;
初始化时,a[i]=1(i=1,2,….r)
设中间的某一个排列为a[1],a[2],…a[r]
则求出下一个排列的算法为:
(1) 从后面向前找,直到找到一个顺序为止(设下标为j-1,则a[j-1]<a[j]
(2) 从a[j]- a[r]中,找出一个a[k]比a[j-1]大的最小元素
(3) 将a[j-1]与a[k]交换
(4) 将a[j],a[j+1]……a[r]由小到大排序。
[程序清单]
*/
#include <iostream>
#include <cstdio>
using namespace std;
const int r=7;
int n,i,s,k,j,i1,t,a[r+1];
void print1(){
int ik;
for(ik=1;ik<=r;++ik) cout<<" "<<a[ik];
cout<<endl;
}
int main( ){
for(i=1;i<=r;++i) ___(1)____;
print1();
s=1;
for(i=2;i<=r;++i) s=s*i;
s=s-1;
for(i=__(2)___;++i){
j=r;
while( __(3)___ ) j=j-1;
k=j;
for(i1=j+1;i1<=r;++i1)
if( __(4)___ ) k=i1;
t=a[j-1];a[j-1]=a[k];a[k]=t;
for(i1=j;i1<=r-1;++i1)
for(k=i1+1;k<=r;++k)
if( ___(5)___ ){
t=a[i1];a[i1]=a[k];a[k]=t;
}
print1();
}
return 0;
}
/*
答案:
(1)、a[i]=i
(2)、l;i<=s
(3)、a[j-1]>a[j]
(4)、a[i1]>a[j-1]&&a[i1]<a[k]
(5)、a[i1]>a[k]
*/
4.[NOIP2000]多项式的乘法
/*
4.[NOIP2000]多项式的乘法。
例如有如下多项式:
P(X)=2X2-X+1, Q(X)=X+1
则:
P(X)·Q(X)=(2X2-X+1)(X+1)=2X3+X2+1
程序说明:
多项式的表示:系数、指数
如上例中: P(X): 系数 指数 Q(X) 系数 指数
2 2 1 1
-1 1 1 0
1 0 0 0
0 0
PXQ的结果存入C中。其输出格式是:依次用一对括号内的(系数,指数)分别来表示。如上例的输出结果表示为:(2,3)(1,2)(1,0)
程序清单
*/
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
int p[15][5],q[15][5],c[25][5];
int main()
{
int i,j,k,l,jp,jq,jc,x,y,x1,y1;
jp=0;
cin>>x>>y;
while( x!=0 )
{
jp++;
p[jp][1]=x;
p[jp][2]=y;
cin>>x>>y;
}
jq=0;
cin>>x>>y;
while( x!=0)
{
jq++;
q[jq][1]=x;
q[jq][2]=y;
cin>>x>>y;
}
jc=1;
c[jc][1]=0;
c[jc][2]=-1000;
for(i=1;i<=jp;i++)
{
___(1)____;
y=p[i][2];
for(j=1;j<=jq;j++)
{
___(2)____;
y1=y+q[j][2];
k=1;
while(y1<c[k][2]) k++;
if(y1==c[k][2]) ___(3)____;
else{
for(l=jc;j>=k;l--)
{
c[l+1][1]=c[l][1];
c[l+1][2]=cp[1][2];
}
c[k][1]=x1;
c[k][2]=y1;
__(4)___;
}
}
}
for(int i=1;i<=jc;i++)
if( __(5)___ ) cout<<'('<<c[i][1]<<','<<c[i][2]<<')';
return 0;
}
/*
答案:
(1)、x=p[i][1]
(2)、 x1=x*q[j][1]
(3)、c[k][1]=c[k][1]+x1
(4)、jc=jc+1或jc++
(5)、 c[i][1]!=0
*/
5.[NOIP2004]Joseph
/*
5.[NOIP2004]Joseph
题目描述:
原始的Joseph问题的描述如下:有n个人围坐在一个圆桌周围,把这n个人依次编号为1,…,n。从编号是1的人开始报数,数到第m个人出列,然后从出列的下一个人重新开始报数,数到第m个人又出列,…,如此反复直到所有的人全部出列为止。比如当n=6,m=5的时候,出列的顺序依次是5,4,6,2,3,1。
现在的问题是:假设有k个好人和k个坏人。好人的编号的1到k,坏人的编号是k+1到2k。我们希望求出m的最小值,使得最先出列的k个人都是坏人。
输入:
仅有的一个数字是k(0 < k <14)。
输出:
使得最先出列的k个人都是坏人的m的最小值。
输入样例:
4
输出样例:
30
程序:
*/
#include <stdio.h>
long k, m, begin;
int check(long remain){
long result = ( ① ) % remain;
if ( ② ){
begin = result; return 1;
}
else return 0;
}
int main(){
long i, find = 0;
scanf("%ld", &k);
m = k;
while( ③ ) {
find = 1; begin = 0;
for (i = 0; i < k; i++)
if (!check( ④ )){
find = 0; break;
}
m++;
}
printf("%ld\n", ⑤ );
return 0;
}
/*
答案:
(1)、begin+m-1
(2)、result>=k(或者k<=result)
(3)、!find(或者find==0)
(4)、2*k-i
(5)、m-1
*/
6、NOIP2006普及组初赛4.2
/*
NOIP2006普及组初赛4.2
2. 由键盘输入一个奇数 P (P<100,000,000),
其个位数字不是 5,求一个整数 S,
使 P×S =1111...1 ( 在给定的条件下,解 S 必存在)。
要求在屏幕上依次输出以下结果:
(1)S 的全部数字。除最后一行外,每行输出 50 位数字。
(2) 乘积的数字位数。
例1:输入p=13,由于13*8547=111111,
则应输出
(1)8547,
(2)6
例2输入p=147,则输出结果应为
(1)755857898715041572184429327286470143613
(2)42,即等式的右端有42个1。
程序:
*/
#include <iostream.h>
#include <iomanip.h>
void main()
{
long p,a,b,c,t,n;
while (1)
{
cout <<"输入 p, 最后一位为 1 或 3 或 7 或 9:"<<endl;
cin >>p;
if ((p%2!=0)&&(p%5!=0)) // 如果输入的数符合要求,结束循环
⑥ ;
}
a=0; n=0;
while (a<p)
{ a=a*10+1;
n++; // 变量a存放部分右端项,n为右端项的位数
}
t=0;
do
{
b=a/p;
cout <<setw(1)<<b;
t++;
if ( ⑦ )
cout <<endl;
c= ⑧ ;
a= ⑨ ;
n++;
} while (c>0);
cout<<endl<<"n="<< ⑩ <<endl;
}
/*
答案:
(1)、break
(2)、t%50==0
(3)、a-p*b(或a-b*p)
(4)、c*10+1
(5)、--n
*/
完善程序 普及篇 7、【NOIP2006提高组】(选排列)
https://blog.csdn.net/dllglvzhenfeng/article/details/130987431
8、NOIP 2007提高组初赛试题完善程序题 5.1(格雷码,Gray Code)
/*
NOIP 2007提高组初赛试题完善程序题5.1(格雷码,Gray Code)
(格雷码,Gray Code)
格雷码是对十进制数的一种二进制编码。
编码顺序与相应的十进制数的大小不一致。其特点是:对于
两个相邻的十进制数,对应的两个格雷码只有一个二进制位不同。
另外,最大数与最小数之间也仅有一个
二进制位不同,以4 位二进制数为例,编码如下:
如果把每个二进制的位看作一个开关,
则将一个数变为相邻的另一个数,只须改动一个开关。因此,
格雷码广泛用于信号处理、数-模转换等领域。
下面程序的任务是:由键盘输入二进制数的位数n (n<16),
再输入一个十进制数m(0≤m<2n),然
后输出对应于m 的格雷码(共n 位,用数组gr[]存放)。
为了将程序补充完整,你必须认真分析上表的规律,
特别是对格雷码固定的某一位,从哪个十进制数
起,由0 变为1,或由1 变为0。
*/
#include <iostream.h>
#include <iomanip.h>
void main()
{
int bound=1,m,n,i,j,b,p,gr[15];
cout<<"Input n,m:"<<endl;
cin>>n>>m;
for(i=1;i<=n;i++) bound= ①;
if(m<0||m>=bound)
{
cout<<"Data error!"<<endl;
②;
}
b=1;
for(i=1;i<=n;i++)
{
p=0; b=b*2;
for( ③ ; j<=m;j++)
if( ④)
p=1-p;
gr[i]=p;
}
for(i=n;⑤)
cout<<setw(1)<<gr[i];
cout<<endl;
return 0;
}
/*
答案:
(1)、bound*2
(2)、return或exit(0)
(3)、j=0
(4)、(j%b-(b/2))==0
(5)、 i>=1;i--或i>0;i--
*/
大量写题是很重要的。特别是对于参加NOI等赛事的选手而言,不应拘泥于一本书或者一个题库,而是应根据自己的实际需求,广泛涉猎自己需要的资源。
对于没有任何编程基础的读者,建议从头按章节顺序学习。如果有一定的基础,那么可以选择性地阅读其中希望进一步巩固的部分,除了第1部分外,后面部分的各章节相对独立,读者可以根据实际情况自行安排学习顺序。
保证程序正确:培养一次写对的能力,提交评测之前要谨慎。学会怎样调试自己的程序。就算感觉对拍办不到,也应该人工生成多组数据,手算结果,然后测试自己的程序对不对。所有犯过的错误都要写笔记,并且不再犯第二次。
如果希望能够熟练掌握算法,增强思维敏捷性,在学习完算法与数据结构后,必须大量地完成相关的题目。
建议本书的读者花费半年的时间学完这本书,至少完成300题,且每周不少于10题。
本书给出的代码仅仅是用来参考的,千万不要照抄。
只有亲自动手实践,学到的东西才是自己的。
熟悉固定套路与算法模板:要反复地敲算法模板,从空白文件开始敲,直到一遍通过为止,这一点你必须很熟练
--------- 摘自《深入浅出程序设计竞赛(基础篇)》
我眼中的竞赛应该主要比思维和实践能力,而不是主要比见识。
大家都知道,编程需要大量的练习,只看和听是不够的。
反过来,如果只是盲目练习,不看不听也是不明智的。
本书的目标很明确---提供算法竞赛入门所必须的一切“看”的蓝本。
有效的“听”要靠教师的辛勤劳动,而有效的“练”则要靠学生自己。
--------- 摘自《算法竞赛入门经典(第2版)》