复试前一周新发布的100个代码题,听说最后真题会从这里抽取。
建一个prime函数判断质数还是合数,main函数中while循环找因子,并/因子,输出
#include
using namespace std;
//质数1,合数0
int prime(int a){
if(a<2)
return 0;
for(int i=2;i<=a/2;i++){
if(a%i==0){
return 0;
}
}
return 1;
}
int main ()
{
int n;
cin>>n;
if(n<2||prime(n)==1){
cout<<n<<"="<<n<<endl;
}
else{
cout<<n<<"=";
while(prime(n)==0){
int i=2;
while(i<=n/2){
if(n%i==0){
n/=i;
cout<<i<<"*";
}
else i++;
}
}
cout<<n<<endl;
}
return 0;
}
max1和max2,当前数大于max1,则max1=a[i],max2=max1
当前数小于max1且大于max2,则直接赋值给max2
#include
using namespace std;
int main ()
{
int a[101],n;
while(cin>>n){
int max1=-2147483648,max2=-2147483648;
for(int i=0;i<n;i++){
cin>>a[i];
}
for(int j=0;j<n;j++){
if(max1<a[j]){
max2=max1;
max1=a[j];
}
else if(max1>a[j]&&max2<a[j]){
max2=a[j];
}
else continue;
}
if(max2==-2147483648)
cout<<"none"<<endl;
else{
cout<<max2;
for(int l=0;l<n;l++){
if(a[l]==max2){
cout<<" "<<l;
}
}
cout<<endl;
}
}
return 0;
}
首先,对龙头和骑士排序,依次对比是否骑士能力>龙头直径,成功则金币增加,对比下一组;失败则对比龙头和下一个骑士。
#include
#include
using namespace std;
int main ()
{
int n,m;
while(cin>>n>>m){
int sum=0;
int tou[n],neng[m];
for(int i=0;i<n;i++)
cin>>tou[i];
for(int k=0;k<m;k++)
cin>>neng[k];
sort(tou,tou+n);
sort(neng,neng+m);
if(n>m||tou[n-1]>neng[m-1])
cout<<"Lose!"<<endl;
else{
int j=0,l=0;
while(l<m){
if(tou[j]!=0&&tou[j]<=neng[l]){
sum+=neng[l];
j++;
l++;
}else
l++;
}
if(j=n-1)
cout<<sum<<endl;
else
cout<<"Lose!"<<endl;
}
}
return 0;
}
#include
#include
using namespace std;
int main ()
{
int n;
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i%2==1)
printf("%4d",(i-1)*n+j);
else
printf("%4d",i*n-j+1);
}
cout<<endl;
}
return 0;
}
#include
#include
using namespace std;
int main ()
{
int n;
char str[50];
cin>>n;
cin.ignore();
for(int i=0;i<n;i++){
gets(str);
int len=strlen(str),c=0;
str[len]=' ';
len++;
for(int i=0;i<len;i++){
if(str[i]==' '&& i-1>=0&&str[i-1]!=' ')
c++;
}
cout<<c<<endl;
}
return 0;
}
#include
#include
#include
using namespace std;
int main(void)
{
int n;
int x;
int temp;
char* arr = new char[10000];
while(cin >> x >> arr){
n = strlen(arr);
long long sum = 0;
for (int i = 0; arr[i]!='\0'; i++)
{
switch (arr[i])
{
case 'A': temp = 10; break;
case 'B': temp = 11; break;
case 'C': temp = 12; break;
case 'D': temp = 13; break;
case 'E': temp = 14; break;
case 'F': temp = 15; break;
case 'G': temp = 16; break;
case 'H': temp = 17; break;
case 'I': temp = 18; break;
case 'J': temp = 19; break;
default: temp = arr[i] - '0'; break;
}
sum = sum + temp * pow(x, n - 1- i);
}
cout << sum <<endl;
}
return 0;
}
#include
using namespace std;
int main(){
int y,z;
char h[20]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J'};
while(cin>>y>>z){
int i;
int *r=new int[15];
int count=1;
for(i=0 ; y >= z ; i++){
r[i]=y%z;
y /= z;
count++;
}
if(y>0)
r[i++]=y;
for(i=count-1 ; i>=0 ; --i)
cout<<h[r[i]];
cout<<endl;
}
return 0;
}
#include
#include
using namespace std;
string subStr(string s1,string s2)
{
string str;
//父串从头开始
for (int i=0;i<s2.length();i++){
//子串从i开始
for (int j=i;j<s2.length();j++){
//若有相同元素
if (s1.find(s2.substr(i,j-i+1))!=-1){
//若有新的子串
if(str.length()<s2.substr(i,j-i+1).length())
str=s2.substr(i,j-i+1);
//相同时取用ascii更小的
else if(str.length()==s2.substr(i,j-i+1).length()){
string str2=s2.substr(i,j-i+1);
if(str.compare(str2)>0)
str=str2;
}
}
else
break;
}
}
return str;
}
int main ()
{
string a,b;
while(cin>>a){
cin>>b;
string str;
str=subStr(a,b);
cout<<str<<endl;
}
return 0;
}
#include
#include
using namespace std;
int fun(int a){
int n=a;
int max;
while(n!=1){
if(n%2==0){
n/=2;
}
else{
n=n*3+1;
if(n>max)
max=n;
}
}
return max;
}
int main ()
{
int m,max=-1;
cin>>m;
for(int n=2;n<m;n++){
fun(n);
if(fun(n)>max){
max=fun(n);
}
}
cout<<max<<endl;
return 0;
}
想半天都搞得位数特别大,搜到了这个很妙的解法。我自己想的是一次性给a*n倍hhh,那不得爆炸了
#include
#include
#include
using namespace std;
int main ()
{
int a,b,n,t;
cin>>a>>b>>n;
for(int i=1;i<=n+2;i++)
{
a*=10;
t=a/b;
a%=b;
if(i>=n){
cout<<t;
}
}
return 0;
}
作者: Turbo时间限制: 1S章节: 枚举
问题描述 :
对于一给定的素数集合 S = {p1, p2, …, pK}, 来考虑那些质因数全部属于S 的数的集合。
这个集合包括,p1, p1p2(即p1乘以p2), p1p3, 和 p1p2p3 (还有其它很多)。
这是个对于一个集合S的丑数集合。注意:我们不认为1 是一个丑数。
你的工作是对于输入的集合S去寻找集合中的第N个丑数。
说明:结果不超过32位整数能表示的范围
比如:S={2, 3, 5, 7}
则前15个丑数为:
2,3,4,5,6,7,8,9,10,12,14,15,16,18,20
输入说明 :
第 1 行: 2个被空格分开的整数:K 和 N , 1<= K<=100 , 1<= N<=100,000.
第 2 行: K 个被空格分开的整数,即集合S的元素
输出说明 :
单独的一行,即第N个丑数。
输入范例 :
4 15 2 3 5 7
输出范例 :
20
#include
using namespace std;
#define MIN 2147483647
int p[101], step[101] = { 0 };//p[]存放质数 step[]存放位置
int ugly[100001];
int main()
{
int n, m;//n个数 求第m个
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
cin >> p[i];
}
ugly[0] = 1;
for (int i = 1; i <= m; i++)
{
int min = MIN;
for (int j = 1; j <= n; j++)
{
//当前质数乘上某丑数成为新丑数
int sum = p[j] * ugly[step[j]];
//新丑数小于原丑数时
while (sum <= ugly[i - 1])
{
//位置后移一个
step[j]++;
sum = p[j] * ugly[step[j]];
}
//找到新的更小值
if (min > sum)
min = sum;
}
ugly[i] = min;
}
cout << ugly[m] << endl;
return 0;
}
}
作者: Turbo时间限制: 1S章节: 基本练习(字符串)
问题描述 :
笨小猴的词汇量很小,所以每次做英语选择题的时候都很头疼。但是他找到了一种方法,经试验证明,用这种方法去选择选项的时候选对的几率非常大!
这种方法的具体描述如下:假设maxn是单词中出现次数最多的字母的出现次数,minn是单词中出现次数最少的字母的出现次数,如果maxn-minn是一个质数,那么笨小猴就认为这是个Lucky
Word,这样的单词很可能就是正确的答案。样例输入
error
样例输出
Lucky Word 2
样例说明
单词error中出现最多的字母r出现了3次,出现次数最少的字母出现了1次,3-1=2,2是质数。
样例输入
olympic
样例输出
No Answer 0
样例说明
单词olympic中所有字母都只出现了1次,1-1=0,0不是质数。
输入说明 :
输入文件只有一行,是一个单词,其中只可能出现小写字母,并且长度小于100。
输出说明 :
输出文件共两行,第一行是一个字符串,假设输入的的单词是Lucky Word,那么输出“Lucky Word”,否则输出“No
Answer”;第二行是一个整数,如果输入单词是Lucky Word,输出maxn-minn的值,否则输出0。输入范例 :
error
输出范例 :
Lucky Word 2
注意数组的输入
#include
#include
#include
using namespace std;
int prime(int a){
if(a<2)
return 0;
for(int i=2;i<=a/2;i++){
if(a%i==0){
return 0;
}
}
return 1;
}
int main ()
{
char a[101],b[26]={};//b数组初始化为0
cin>>a;
int len=strlen(a);
for(int i=0;i<len;i++)
{
b[a[i]-95]++; //a对应0 z对应25 对应位置++
}
int max=-10,min=500;
for(int i=0;i<26;i++){
if(b[i]>max)
max=b[i];
if(b[i]<min&& b[i]!=0)
min=b[i];
}
if(prime(max-min)==1){
cout<<"Lucky Word"<<endl;
cout<<max-min<<endl;
}
else{
cout<<"No Answer"<<endl;
cout<<0<<endl;
}
return 0;
}
作者: Turbo时间限制: 1S章节: 基本练习(字符串)
问题描述 :
给定一个长度为n的字符串S,还有一个数字L,统计长度大于等于L的出现次数最多的子串(不同的出现可以相交),如果有多个,输出最长的,如果仍然有多个,输出第一次出现最早的。
输入说明 :
第一行一个数字L。 第二行是字符串S。 L大于0,且不超过S的长度。
n<=60 S中所有字符都是小写英文字母。
输出说明 :
一行,题目要求的字符串。
输入样例1: 4 bbaabbaaaaa
输出样例1: bbaa
输入样例2: 2 bbaabbaaaaa
输出样例2: aa
输入范例 :
4 bbaabbaaaaa
输出范例 :
bbaa
#include
#include
#include
#define max 1000
//返回str中从start位置开始的len个字符
void getsub(char str[],int start,int len,char subs[]){
int i,j=0;
for(i=start;i<start+len;i++)
subs[j++]=str[i];
subs[j]='\0';
}
int main(){
int i,j,k,c,maxc,maxlen,L,len;
char s[max],sub[max],tsub[max],maxsub[max];
scanf("%d",&L);
getchar();
gets(s);
len=strlen(s);
if(len==L)
puts(s);
else{
//最大出现次数以及字符串长度
maxc=0;
maxlen=0;
//每次选取字符串长度为i
for(i=L;i<=len;i++){
for(j=0;j<=len-i;j++){
//首先获得一个长度i的子字符串
getsub(s,j,i,sub);
c=0;
for(k=0;k<=len-i;k++){
getsub(s,k,i,tsub);
//统计sub子串出现的次数
if(strcmp(sub,tsub)==0)
c++;
}
if(maxc<c||(maxc==c&&i>maxlen)){
strcpy(maxsub,sub);
maxc=c;
maxlen=i;
}
}
}
puts(maxsub);
}
return 0;
}
第二种解法
#include
#include
int main()
{
int l, maxn, cnt,i,k,j,t,len;
char s[60], *s1, *s2, *ans;
scanf("%d", &l);
scanf("%s",s);
len =strlen(s);
maxn = cnt = 0;
for(i = l; i <= len; i++)//最低子串长度
{
for(j = 0; j + i <= len; j++)
{
cnt = 0;
s1= &s[j];//记录子串起始位置
for(k = 0; k+i <= len; k++)//这个循环用于查找子串重复次数
{
s2 = &s[k];
if(!strncmp(s1,s2,i))
cnt++;
}
if(cnt > maxn)
{
t=i;
ans = s1;
maxn = cnt;
}
else if(cnt==maxn && i>t)
{
t=i;
ans = s1;
maxn = cnt;
}
}
}
for(k=0;k<t;k++)
{
printf("%c",*(ans+k));
}
return 0;
}
作者: Turbo时间限制: 1S章节: 基本练习(字符串)
问题描述 :
Anagrams指的是具有如下特性的两个单词:在这两个单词当中,每一个英文字母(不区分大小写)所出现的次数都是相同的。例如,“Unclear”和“Nuclear”、“Rimon”和“MinOR”都是Anagrams。编写一个程序,输入两个单词,然后判断一下,这两个单词是否是Anagrams。每一个单词的长度不会超过80个字符,而且是大小写无关的。
输入说明 :
输入有两行,分别为两个单词。
输出说明 :
输出只有一个字母Y或N,分别表示Yes和No。
输入范例 :
aabbcc ccbbaa
输出范例 :
Y
巧妙使用ascii码与数组
#include
#include
#include
using namespace std;
int main ()
{
char a[101],c[101],b1[26]={},b2[26]={};
cin>>a;
cin>>c;
int flag=1;
int len1=strlen(a);
int len2=strlen(c);
for(int i=0;i<len1;i++)
if(a[i]>95)
b1[a[i]-95]++; //a对应0 z对应25 对应位置++
else
b1[a[i]-63]++;
for(int i=0;i<len2;i++)
if(c[i]>95)
b2[c[i]-95]++; //a对应0 z对应25 对应位置++
else
b2[c[i]-63]++;
for(int i=0;i<26;i++){
if(b1[i]!=b2[i])
flag=0;
}
if(flag==0)
cout<<"N"<<endl;
else
cout<<"Y"<<endl;
return 0;
}
作者: Turbo时间限制: 1S章节: 基本练习(字符串)
问题描述 :
从1999年10月1日开始,公民身份证号码由15位数字增至18位。(18位身份证号码简介)。升级方法为:
1、把15位身份证号码中的年份由2位(7,8位)改为四位。 2、最后添加一位验证码。验证码的计算方案: 将前 17
位分别乘以对应系数 (7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2) 并相加,然后除以 11 取余数,0-10
分别对应 1 0 x 9 8 7 6 5 4 3 2。
请编写一个程序,用户输入15位身份证号码,程序生成18位身份证号码。假设所有要升级的身份证的四位年份都是19××年输入说明 :
一个15位的数字串,作为身份证号码
不用判断输入的15位字符串是否合理
输出说明 :
一个18位的字符串,作为升级后的身份证号码
输入范例 :
110105491231002
输出范例 :
11010519491231002x
char转int:
a[ i ] - ’ 0 ’
#include
#include
using namespace std;
int main ()
{
char a[15];
cin>>a;
char b[18];
char c[17]={7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};
char d[11]={'1','0','x','9','8','7','6','5','4','3','2'};
for(int i=0;i<17;i++){
if(i<6)
b[i]=a[i];
else if(i==6)
b[i]='1';
else if(i==7)
b[i]='9';
else
b[i]=a[i-2];
}
int sum=0;
int x,y;
for(int i=0;i<17;i++){
x=b[i]-'0';
y=c[i];
sum+=x*y;
}
int yushu;
yushu=sum%11;
b[17]=d[yushu];
for(int i=0;i<18;i++){
cout<<b[i];
}
return 0;
}
作者: Turbo时间限制: 1S章节: 基本练习(数组)
问题描述 :
为丰富男生节活动,女生设置彩票抽奖环节,规则如下: 1、每张彩票上印有7个各不相同的号码,且这些号码的取值范围为[1, 33];
2、每次在兑奖前都会公布一个由七个互不相同的号码构成的中奖号码; 3、共设置7个奖项,特等奖和一等奖至六等奖。兑奖规则如下:
特等奖:要求彩票上的7个号码都出现在中奖号码中; 一等奖:要求彩票上的6个号码出现在中奖号码中;
二等奖:要求彩票上的5个号码出现在中奖号码中; …… 六等奖:要求彩票上的1个号码出现在中奖号码中;
注:不考虑号码出现的顺序,例如若中奖号码为23 31 1 14 19 17 18,则彩票12 8 9 23 1 16
7由于其中有两个号码(23和1)出现在中奖号码中,所以该彩票中了五等奖。
现已知中奖号码和李华买的若干彩票的号码,请你写一个程序判断他的彩票中奖情况。输入说明 :
第一行一个正整数n,表示彩票数量,第二行7个整数,表示中奖号码,下面n行每行7个整数,描述n张彩票。
n<=100000
输出说明 :
7个数字,第1个数字表示特等奖的中奖张数,第2个数字表示一等奖的中奖张数,第3个数字表示二等奖的中奖张数……第7个数字表示六等奖的中奖张数。
每个数字后都跟一个空格。
输入范例 :
3 1 2 3 4 5 6 7 11 12 13 14 15 16 17 12 13 14 15 16 17 18 8 7 10 9 31
30 29 输出范例 :0 0 0 0 0 0 1
循环和if混用
#include
using namespace std;
int main ()
{
int n,x[7],zj[7]={0};
int a0[33]={0};
cin>>n;
//输入中奖号码
for(int i=0;i<7;i++){
cin>>x[i];
}
//匹配中奖数组a0
for(int i=0;i<7;i++){
a0[x[i]]++;
}
for(int i=0;i<n;i++){
int a1[33]={0};
int sum=0;
int y[7];
//输入抽奖号码
for(int j=0;j<7;j++){
cin>>y[j];
}
for(int j=0;j<7;j++){
a1[y[j]]++;
}
for(int j=0;j<33;j++){
if(a0[j]==a1[j]&&a0[j]!=0)
sum++;
}
zj[7-sum]++;
}
for(int k=0;k<7;k++)
cout<<zj[k]<<" ";
return 0;
}
作者: Turbo时间限制: 1S章节: 基本练习(数组)
问题描述 :
如果一个合数由两个质数相乘而得,那么我们就叫它是质数们的直接后代。现在,给你一系列自然数,判断它们是否是质数的直接后代。
输入说明 :
第一行一个正整数T,表示需要判断的自然数数量 接下来T行,每行一个要判断的自然数
1<=T<=20 2<=要判断的自然数<=105
输出说明 :
共T行,依次对于输入中给出的自然数,判断是否为质数的直接后代,是则输出Yes,否则输出No
输入范例 :
4 3 4 6 12 输出范例 :
No Yes Yes No
#include
using namespace std;
int prime(int a){
for(int i=2;i<=a/2;i++){
if(a%i==0)
return 0;
}
return 1;
}
int main ()
{
int t;
cin>>t;
for(int i=0;i<t;i++){
int n;
cin>>n;
int flag=0;
if(prime(n)==1)
cout<<"No"<<endl;
else{
for(int j=2;j<=n/2;j++){
if(n%j==0){
if(prime(j)==1&&prime(n/j)==1)
flag=1;
}
else continue;
}
if(flag==1)
cout<<"Yes"<<endl;
else
cout<<"No"<<endl;
}
}
return 0;
}
作者: Turbo时间限制: 1S章节: 基本练习(数组)
问题描述 :
在C/C++语言中,整型所能表示的范围一般为-231到231(大约21亿),即使long
long型,一般也只能表示到-263到263。要想计算更加规模的数,就要用软件来扩展了,比如用数组或字符串来模拟更多规模的数及共运算。
现在输入两个整数,请输出它们的乘积。输入说明 :
两行,每行一个正整数,每个整数不超过10000位
输出说明 :
一行,两个整数的乘积。
输入范例 :
10000 234 输出范例 :
2340000
#include
#include
#include
using namespace std;
int main()
{
string str1, str2;
cin >> str1 >> str2;
int len1 = (int)str1.length();
int len2 = (int)str2.length();
int *p = new int[len1 + len2]();//数组初始化
reverse(str1.begin(), str1.end());
reverse(str2.begin(), str2.end());
for (int i = 0; i < len1; i++)
{
for (int j = 0; j < len2; j++)
{
p[i + j] += (str1[i] - '0')*(str2[j] - '0');
}
}
for (int i = 0; i < len1+ len2; i++)
{
p[i + 1] += p[i] / 10;
p[i] %= 10;
}
int len = len1 + len2 - 1;
while (len>=0&&p[len] == 0)
{
len--;
}
if (len < 0)
cout << 0 << endl;
else
{
len++;
reverse(p, p + len);
for (int i = 0; i < len; i++)
{
cout << p[i];
}
cout << endl;
}
return 0;
}
作者: Turbo时间限制: 1S章节: 基本练习(数组)
问题描述 :
给定n和len,输出n!末尾len位。
输入说明 :
一行,两个正整数n和len。
n<=30, len<=10。
输出说明 :
一行,一个字符串,表示答案。长度不足用前置零补全。
输入范例 :
6 5 输出范例 :
00720
#include
#include
#include
#include
int main()
{
char s[2000];
int n,len,i,k=0,num,lenj=1,j,jin=0;
memset(s,'0',sizeof(s));
s[0]='1';
scanf("%d%d",&n,&len);
for(i=2;i<=n;i++)
{
k=0;
jin=0;
//循环取余
for(j=0;j<10;j++)
{
jin=jin+(s[j]-'0')*i;
s[k]=jin%10+'0';
k++;
jin=jin/10;
}
}
//倒过来打印
for(i=len-1;i>=0;i--)
{
printf("%c",s[i]);
}
printf("\n");
return 0;
}
作者: Turbo时间限制: 1S章节: 基本练习(数组)
问题描述 :
道德经曰:一生二,二生三,三生万物。
对于任意正整数n,我们定义d(n)的值为为n加上组成n的各个数字的和。例如,d(23)=23+2+3=28,
d(1481)=1481+1+4+8+1=1495。
因此,给定了任意一个n作为起点,你可以构造如下一个递增序列:n,d(n),d(d(n)),d(d(d(n)))…例如,从33开始的递增序列为:
33, 39, 51, 57, 69, 84, 96, 111, 114, 120, 123, 129, 141, …
我们把n叫做d(n)的生成元,在上面的数列中,33是39的生成元,39是51的生成元,等等。有一些数字甚至可以有两个生成元,比如101,可以由91和100生成。但也有一些数字没有任何生成元,如42。我们把这样的数字称为寂寞的数字。输入说明 :
一行,一个正整数n。
n<=10000
输出说明 :
按照升序输出小于n的所有寂寞的数字,每行一个。
#include
int son(int num)
{
if(num<10)
return num;
else return num%10+son(num/10);
}
int main()
{
int a[10000],b[10000];
int n,i;
scanf("%d",&n);
for(i=0;i<=n;i++)
{
//原数+每一位上的数
a[i]=i+son(i);
}
for(i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(i==a[j])
b[i]=1;
}
}
for(i=0;i<n;i++)
{
if(b[i]!=1)
printf("%d\n",i);
}
return 0;
}
作者: Turbo时间限制: 1S章节: 枚举
问题描述 :
给定一个正整数k(3≤k≤15),把所有k的方幂及所有有限个互不相等的k的方幂之和构成一个递增的序列,例如,当k=3时,这个序列是:
1,3,4,9,10,12,13,…
(该序列实际上就是:30,31,30+31,32,30+32,31+32,30+31+32,…)
请你求出这个序列的第N项的值(用10进制数表示)。 例如,对于k=3,N=100,正确答案应该是981。输入说明 :
只有1行,为2个正整数,用一个空格隔开:k N (k、N的含义与上述的问题描述一致,且3≤k≤15,10≤N≤1000)。
输出说明 :
计算结果,是一个正整数(在所有的测试数据中,结果均不超过2.1*109)。(整数前不要有空格和其他符号)。
输入范例 :
3 100 输出范例 :
981 Donghua University Online Judge 1.0
#include
#include
int main()
{
int n,s[1001];
int k;
scanf("%d%d",&k,&n);
int loc=0;
int num=1;
int i=1;
while(loc<n)
{
//控制幂次
int temp=loc;
//首个为k的0次方=1
s[loc++]=num;
for(i=0;i<temp&&loc<n;i++)
{
//分别加从0开始的幂次
s[loc++]=num+s[i];
}
//下一个幂次要升1
num=num*k;
}
printf("%d\n",s[loc-1]);
return 0;
}
作者: xxx时间限制: 1S章节: 一维数组
问题描述 :
孪生素数就是指相差2的素数对,例如3和5,5和7,11和13…。这个猜想正式由希尔伯特在1900年国际数学家大会的报告上第8个问题中提出,可以这样描述:存在无穷多个素数p,使得p
- 2是素数。素数对(p, p + 2)称为孪生素数。
现在给定任何正整数 N (< 10 ^ 5), 请你计算不大于 N 的孪生素数的对数。
输入说明 :
你的程序必须从标准输入中读取测试用例。输入文件由几组测试用例组成。每组测试用例占一行, 其中包含一个整数 N。当输入的
N为负数表示结束输入。输出说明 :
对于每组测试数据,输出一行,包括一个整数,表示不大于 N 的孪生素数的对数
输入范例 :
5 7 13 8 15
-16 输出范例 :1 2 3 2 3
Donghua University Online Judge 1.0
很简单哈
#include
#include
#include
int isprime(int num)
{
if(num<2)
return 0;
for(int i=2;i<=sqrt(num);i++)
{
if(num%i==0)
return 0;
}
return 1;
}
int main()
{
int n,i,k;
while(~scanf("%d",&n))
{
if(n<0)
break;
k=0;
for(i=2;(i+2)<=n;i++)
{
if(isprime(i)&&isprime(i+2))
{
k++;
}
}
printf("%d\n",k);
}
return 0;
}
作者: Turbo时间限制: 1S章节: 基本练习(数组)
问题描述 :
给定一个序列,每次询问序列中第l个数到第r个数中第K大的数是哪个。
注意,由于存在相等的元素,因此,第2大的数可能和第1大的数相等。
输入说明 :
第一行包含一个数n,表示序列长度。
第二行包含n个正整数,表示给定的序列。
第三个包含一个正整数m,表示询问个数。
接下来m行,每行三个数l,r,K,表示询问序列从左往右第l个数到第r个数中,从大往小第K大的数是哪个。序列元素从1开始标号。
n,m<=1000;
保证k<=(r-l+1),序列中的数<=106。
输出说明 :
总共输出m行,每行一个数,表示询问的答案。
输入范例 :
5 1 5 3 4 5 2 1 5 2 2 3 2
输出范例 :
5 3
Donghua University Online Judge 1.0
根据输入的起始位置,确定截取区间,按照从大到小进行排序,第k大数即为第k-1下标位置上的数。
#include
#include
#include
#include
int cmp(const void*_a,const void*_b)//从大到小排序
{
int *a=(int *)_a;
int *b=(int *)_b;
return *b-*a;
}
int main()
{
int *a;
int n,m,i,j;
scanf("%d",&n);
a=(int *)malloc(sizeof(int)*n);
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
scanf("%d",&m);
for(i=0;i<m;i++)
{
int l,r,k,p=0;
int *temp;
scanf("%d%d%d",&l,&r,&k);
temp=(int *)malloc(sizeof(int)*(r-l+1));
for(j=l-1;j<r;j++)//把第l个到第r个的元素都提取出来,存在temp数组中,然后从大到小排序之后就简单多了
{
temp[p++]=a[j];
}
qsort(temp,p,sizeof(int),cmp);
printf("%d\n",temp[k-1]);
}
return 0;
}
作者: Turbo时间限制: 1S章节: 基本练习(数组)
问题描述 :
在一个有限的正整数序列中,有些数会多次重复出现在这个序列中。
如序列:3,1,2,1,5,1,2。其中1就出现3次,2出现2次,3出现1 次,5出现1次。
你的任务是对于给定的正整数序列,从小到大依次输出序列中出现的数及出现的次数。输入说明 :
第一行正整数n,表示给定序列中正整数的个数。 第二行是n 个用空格隔开的正整数x,代表给定的序列。
n<=1000;0
输出说明 :
若干行,每行两个用一个空格隔开的数,第一个是数列中出现的数,第二个是该数在序列中出现的次数。
输入范例 :
12 8 2 8 2 2 11 1 1 8 1 13 13 输出范例 :
1 3 2 3 8 3 11 1 13 2
Donghua University Online Judge 1.0
思路:
新数组b,出现一次则++,然后从头输出b(值非0则输出
#include
#include
#include
#include
#include
#include
long s[1000001]={0};
int main()
{
int *a;
int *s;
int n,i,j=0;
scanf("%d",&n);
a=(int *)malloc(sizeof(int)*n);
s=(int *)malloc(sizeof(int)*1000001);
memset(s,0,1000001);
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
s[a[i]]++;
}
for(i=0;i<1000001;i++)
{
if(s[i]>0)
printf("%d %d\n",i,s[i]);
}
return 0;
}
作者: Turbo时间限制: 1S章节: 基本练习(数组)
问题描述 :
任意一个四位数,只要它们各个位上的数字是不全相同的,就有这样的规律:
1)将组成该四位数的四个数字由大到小排列,形成由这四个数字构成的最大的四位数;
2)将组成该四位数的四个数字由小到大排列,形成由这四个数字构成的最小的四位数(如果四个数中含有0,则得到的数不足四位);
3)求两个数的差,得到一个新的四位数(高位零保留)。 重复以上过程,最后一定会得到的结果是6174。 比如:4312 3087
8352 6174,经过三次变换,得到6174输入说明 :
一个四位整数,输入保证四位数字不全相同
输出说明 :
一个整数,表示这个数字经过多少次变换能得到6174
输入范例 :
4312 输出范例 :
3
解法:若不为6174,则计算出四位数的最大值,最小值,差,然后比较是否为6174,若否,次数加一,循环上述过程。
//每次把number中的各个位置上的数字分解到temp中,排序之后,通过遍历来构成max和min,max-min来构造新的number
#include
#include
#include
#include
#include
#include
int cmp(const void*_a,const void*_b)
{
int *a=(int*)_a;
int *b=(int*)_b;
return *a-*b;
}
int main()
{
int n,i,count=0;
scanf("%d",&n);
int num=n;
while(num!=6174)
{
i=0;
int max=0,min=0;
int number=num;
int temp[4]={0};
while(number>0)
{
temp[i++]=number%10;
number=number/10;
}
qsort(temp,4,sizeof(int),cmp);
for(int j=0;j<4;j++)
{
max=max*10+temp[4-j-1];
min=min*10+temp[j];
}
num=max-min;
count++;
}
printf("%d\n",count);
return 0;
}
作者: Turbo时间限制: 1S章节: 基本练习(数组)
问题描述 :
Torry从小喜爱数学。一天,老师告诉他,像2、3、5、7……这样的数叫做质数。Torry突然想到一个问题,前10、100、1000、10000……个质数的乘积是多少呢?他把这个问题告诉老师。老师愣住了,一时回答不出来。于是Torry求助于会编程的你,请你算出前n个质数的乘积。不过,考虑到你才接触编程不久,Torry只要你算出这个数模上50000的值。
输入说明 :
仅包含一个正整数n,其中n<=100000。
输出说明 :
输出一行,即前n个质数的乘积模50000的值。
输入范例 :
3 输出范例 :
30
思路:求出前n个质数,对其进行乘积运算,并对50000进行取模
#include
using namespace std;
int prime(long n)
{
if(n==1)
return 0;
if(n==2||n==3)
return 1;
long t=sqrt(n);
for(long i=2; i<=t; i++)
{
if(n%i==0)
return 0;
}
return 1;
}
int main()
{
long long n;
while(cin>>n)
{
long long sum=1;
for(long long i=2;; i++)
{
if(prime(i))
{
sum=sum*i;
sum=sum%50000;
n--;
}
if(n==0)
break;
}
cout<<sum<<endl;
}
return 0;
}
作者: Turbo时间限制: 1S章节: 基本练习(数组)
问题描述 :
同在一个高中,他却不敢去找她,虽然在别人看来,那是再简单不过的事。暗恋,是他唯一能做的事。他只能在每天课间操的时候,望望她的位置,看看她倾心的动作,就够了。操场上的彩砖啊,你们的位置,就是他们能够站立的地方,他俩的关系就像砖与砖之间一样固定,无法动摇。还记得当初铺砖的工人,将整个操场按正方形铺砖(整个操场可视为R行C列的矩阵,矩阵的每个元素为一块正方形砖块),正方形砖块有两种,一种为蓝色,另一种为红色。我们定义他和她之间的“爱情指标”为最大纯色正方形的面积,请你写一个程序求出“爱情指标”。
输入说明 :
第一行两个正整数R和C,R和C都不超过200。 接下来R行C列描述整个操场,红色砖块用1来表示,蓝色砖块用0来表示。
输出说明 :
一个数,表示他和她之间的“爱情指标”。
输入范例 :
5 8 0 0 0 1 1 1 0 1 1 1 0 1 1 1 1 1 0 1 1 1 1 1 0 1 1 0 1 1 1 1 1 0 1
1 1 0 1 1 0 1 输出范例 :9 Donghua University Online Judge 1.0
思路:对于输入的二维数组,遍历每个节点,判断由该节点生成的爱情指标的最大值,最后输出最大值。
#include
using namespace std;
int love[201][201] = { 0 };
bool isLove(int x, int y,int len)
{
int color = love[x][y];
x++;
y++;
if (love[x][y] != color) return false;
for (int i = 1; i <= len; i++)//判断正方形内是否全部为同一颜色
{
if (love[x - i][y] != color) return false;//y列检查
if (love[x][y - i] != color) return false;//x行检查
}
return true;
}
int main()
{
int r, c;
cin >> r >> c;
for (int i = 1; i <= r; i++)
{
for (int j = 1; j <= c; j++)
{
cin >> love[i][j];
}
}
int max = 1;
bool flag = 0;
for (int i = 1; i <= r; i++)
{
for (int j = 1; j <= c; j++)
{
if (r - i < max)//剩余高度小于最大边长跳出
{
flag = 1;
break;
}
if (c - j < max)//剩余宽度小于最大边长 换行
{
continue;
}
//判断最大边长
int len = 1, x = i, y = j;
while (x < r&&y < c)
{
if (isLove(x, y,len))
{
x++, y++, len++;
if (len>max) max = len;
}
else
{
break;
}
}
}
if (flag)
break;
}
cout << max*max<< endl;
return 0;
}
作者: ZhouMingLiang时间限制: 10S章节: 一维数组
问题描述 :
有一次,明明的公司举行忘年会。忘年会的高潮部分是最后的抽大奖环节。公司为了增加活动的气氛,并没有按传统的抽奖方式来抽,而是进行了一个游戏:逐步逐步地淘汰人,而最后剩下的人,将会得到大奖。
这个游戏的方式如下:首先公司的全部职员围成一个圈,然后确定一个淘汰数X,接着就从其中的一个人开始,从1数数,当数到X时,那个人就被淘汰出局,接着下一个人再从1开始数数,一直这样重复下去,直到剩下最后一个人,那个人就是最后的大奖得主。
例如,公司有5个人,淘汰数定为2,则一开始五个人排成一圈,依次编号为:1、2、3、4、5;
首先从编号1的人开始数数,数到2后,编号2淘汰,这样只剩下4个人:1、3、4、5;
接着从编号3的人开始数,数到2后,编号4淘汰,这样只剩下3个人:1,3、5;
接着从编号5的人开始数,数到2后,编号1淘汰,这样只剩下2个人:3、5;
最后从编号为3的人开始数,数到2后,编号5淘汰,最后编号为3的那个人就获得了最终的大奖。 (注:以上的淘汰顺序为2 4 1 5 3。)由于明明的运气十分地差,最后第二个被淘汰,与大奖失之交臂,十分郁闷。他想知道自己被淘汰的全过程,于是他想请你帮个忙,帮他写一个程序,明明把他公司的人数告诉你,并且把那个淘汰数也告诉你,你的程序能够根据这两个数计算出淘汰人的具体顺序,即把淘汰人的编号按顺序输出。
明明的问题可以归结为:给你一个公司的人数N和一个淘汰数X,你的程序模拟上面描述的淘汰方式,输出淘汰人的编号顺序。
输入说明 :
你写的程序要求从标准输入设备中读入测试数据作为你所写程序的输入数据。标准输入设备中有多组测试数据,每组测试数据仅一行,每组测试数据有两个整数N(1
输出说明 :
对于每一组测试数据,你写的程序要求计算出一组相应的运算结果,并将这一组运算结果作为你所写程序的输出数据依次写入到标准输出设备中。每组运算结果为N个整数,即淘汰人的编号的顺序,每个数之间用一个空格隔开。每组运算结果单独形成一行数据,其行首和行尾都没有任何空格,每组运算结果与其后一组运算结果之间没有任何空行,第一组运算结果前面以及最后一组运算结果后面也都没有任何空行。
注:通常,显示屏为标准输出设备。输入范例 :
5 2 5 6 99 1 输出范例 :
2 4 1 5 3 1 3 2 5 4 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
90 91 92 93 94 95 96 97 98 99
解法:本题考察约瑟夫环的顺序输出问题,n个人每报m次就要出列一个,其实是模拟这个出列的过程。我们每次要计算得到出列人的下标,同时要注意所报的数能否整除m,能的话就让这个人出列,然后标记一下st[],把这个人放到答案数组中,当所有人都出列时,顺序也就拍好了。
#include
using namespace std;
typedef long long LL;
int a,b,c,n,m;
bool st[110];//判断是否out的数组
int main()
{
while(cin>>n>>m)
{
vector<int> v;
//cur:当前人下标 cnt:报的数 tot:一共出去的人数
int cur=0,cnt=1,tot=0;
memset(st,0,sizeof st);//st全部设置为0
while(tot!=n) // out人数是否满
{
if(st[cur]) // 已out,直接找下一个人的下标
{
cur=(cur+1)%n;
continue;
}
if(cnt%m==0) // 准备out
{
st[cur]=1;
tot++;
v.push_back(cur+1); //我们输出的序号是1~n,所以要+1偏移一下。
}
cur=(cur+1)%n; // 找到下个人的下标,继续报数
cnt++;
}
for(int i=0;i<v.size()-1;i++) cout<<v[i]<<" ";
cout<<v[v.size()-1]<<endl;
}
return 0;
}
作者: Turbo时间限制: 1S章节: 基本练习(循环)
问题描述 :
78这个数可以表示为连续正整数的和,1+2+3,18+19+20+21,25+26+27。 输入一个正整数 n(<=10000)
输出 m 行(n有m种表示法),每行是两个正整数a,b,表示a+(a+1)+…+b=n。 对于多种表示法,a小的方案先输出。输入说明 :
输入一个正整数 n(<=10000)
输出说明 :
输出 m 行(n有m种表示法),每行是两个正整数a,b
对于多种表示法,a小的方案先输出。
输入范例 :
78 输出范例 :
1 12 18 21 25 27
#include
#include
#include
#include
#include
#include
#include
#include
#define ll long long
int rc[201][201];
using namespace std;
int main()
{
int n;
cin >> n;
for (int i = 1; i < n; i++)
{
int s = 0;
for (int j = i; j < n; j++)
{
s += j;
if (s == n)
{
printf("%d %d\n", i, j);
break;
}
}
}
}
作者: Turbo时间限制: 1S章节: 基本练习(数组)
问题描述 :
小明正在玩一个“翻硬币”的游戏。
桌上放着排成一排的若干硬币。我们用 * 表示正面,用 o 表示反面(是小写字母,不是零)。
比如,可能情形是:oo*oooo
如果同时翻转左边的两个硬币,则变为:oooo***oooo
现在小明的问题是:如果已知了初始状态和要达到的目标状态,每次只能同时翻转相邻的两个硬币,那么对特定的局面,最少要翻动多少次呢?
我们约定:把翻动相邻的两个硬币叫做一步操作
输入说明 :
两行等长的字符串,分别表示初始状态和要达到的目标状态。每行的长度<1000
输出说明 :
一个整数,表示最小操作步数。
比如:
输入
ooo***
ooo***输出
1
输入范例 :
********** oo
输出范例 :
5
#include
using namespace std;
int main()
{
char s1[1000];
char s2[1000];
int cr[1000]; //记录两个字符串的比较结果。0为相同,1为不同。
while(cin>>s1){
cin>>s2;
int l;
for(l=0;s1[l]!='\0';l++); //计算长度
for(int i=0;i<l;i++){ //比较两个字符串,并记录结果
if(s1[i]==s2[i])
cr[i]=0;
else
cr[i]=1;
}
int f=-1; //记录标记位
int _count=0;
for(int i=0;i<l;i++){
if(cr[i]==1){ //检测到一个 1
if(f==-1){ //如果前面没有记录的1的下标,记录当前1的下标
f=i;
}
else{ //如果前面有一个1了
_count+=i-f;
f=-1;
}
}
}
cout<<_count<<endl;
}
return 0;
}
作者: Turbo时间限制: 1S章节: 基本练习(数组)
问题描述 :
有n个小朋友围坐成一圈。老师给每个小朋友随机发偶数个糖果,然后进行下面的游戏:
每个小朋友都把自己的糖果分一半给左手边的孩子。
一轮分糖后,拥有奇数颗糖的孩子由老师补给1个糖果,从而变成偶数。
反复进行这个游戏,直到所有小朋友的糖果数都相同为止。
你的任务是预测在已知的初始糖果情形下,老师一共需要补发多少个糖果。
输入说明 :
程序首先读入一个整数N(2
输出说明 :
要求程序输出一个整数,表示老师需要补发的糖果数。
输入范例 :
3 2 2 4
输出范例 :
4
#include
using namespace std;
int cns=0;
int n;
int dfs(int *s)
{
int str[n];
int xb=1;
//所有小朋友的糖一样多
for(int i=1;i<n;i++)
{
if(s[i]!=s[0])
{
xb=0;
}
}
if(xb) return 0;
for(int i=0;i<n;i++)
{
//后一个小朋友得到前一个的一半
str[i]=s[i]/2;
}
//第一个小朋友得到上一个的一半和
s[0]=str[n-1]+s[0]/2;
if(s[0]%2==1)
{
s[0]=s[0]+1;
cns++;
}
for(int i=1;i<n;i++)
{
s[i]=str[i-1]+s[i]/2;
if(s[i]%2==1)
{
s[i]=s[i]+1;
cns++;
}
}
return dfs(s);
}
int main()
{
cin>>n;
int str[n];
for(int i=0;i<n;i++)
{
cin>>str[i];
}
dfs(str);
cout<<cns<<endl;
return 0;
}
作者: Turbo时间限制: 1S章节: 基本练习(数组)
问题描述 :
扫雷游戏你一定玩过吧!现在给你若干个n×m的地雷阵,请你计算出每个矩阵中每个单元格相邻单元格内地雷的个数,每个单元格最多有8个相邻的单元格。
0输入说明 :
输入包含若干个矩阵,对于每个矩阵,第一行包含两个整数n和m(0
输出说明 :
对于第i个矩阵,首先在单独的一行里打印序号:“Field
#i:”,接下来的n行中,读入的’.'应被该位置周围的地雷数所代替。输出的每两个矩阵必须用一个空行隔开。
解法:对于输入的二位字符型数组,遍历数组。对于安全区,比较周围最多八个数,判断是否有地雷,若有则记录个数。对于雷区,不比较。
#include
using namespace std;
char a[100][100];
int m,n;
void bb(int i,int j)
{
int sum=0,x=i-1,y=j-1,x1=i+1,y1=j+1,i1,j1;
if(a[i][j]=='*')
{
cout<<"*";
}
else
{
if(i==0)//判断边界
{
x=0;
}
if(j==0)
{
y=0;
}
if(i==m-1)
{
x1=m-1;
}
if(j==n-1)
{
y1=n-1;
}
for(i1=x; i1<=x1; i1++)//若该点非边界点,判断其周围八个点地雷的个数
{
for(j1=y; j1<=y1; j1++)
{
if(a[i1][j1]=='*')
{
sum++;
}
}
}
cout<<sum;
}
}
int main()
{
int i,j,count=0;
char x;
while(1)
{
cin>>m>>n;
if(m==0&&n==0)
{
break;
}
count++;
for(i=0; i<m; i++)
{
for(j=0; j<n; j++)
{
cin>>x;
if(x==10)//遇到换行,保持j不越界
{
j--;
}
if(x!=10)
{
a[i][j]=x;
}
}
}
cout<<"Field #"<<count<<endl;
for(i=0; i<m; i++)
{
for(j=0; j<n; j++)
{
bb(i,j);
}
cout<<endl;
}
cout<<endl;
}
return 0;
}
作者: turbo时间限制: 1S章节: 字符串
问题描述 :
s01串初始为"0"
按以下方式变换:
0变1,1变01
所以,变换规律如下:
1次变换后:1; 2次变换后:01; 3次变换后:101; 4次变换后:01101; 5次变换后:10101101;
…
输入说明 :
输入1个整数n,范围为0<=n<=19,表示变换的次数
输出说明 :
n次变换后的s01串,行首行尾无空格,也无空行。
循环替换吧,从头扫描
这是一个递归问题,当n=0时,输出为0,当n=1时,输出为1,当n>=2时,输出第n-2个字符,加第n-1个字符。
#include
using namespace std;
string fun(int n);
int main()
{
int n;
cin >> n;
cout << fun(n) << endl;
return 0;
}
string fun(int n)
{
if(n == 0)
return "0";
else if(n == 1)
return "1";
else
return fun(n-2) + fun(n-1);
}
作者: Turbo时间限制: 1S章节: 基本练习(字符串)
问题描述 :
安全局搜索到了一批(n个)身份证号码,希望按出生日期对它们进行从大到小排序,如果有相同日期,则按身份证号码从大到小进行排序。身份证号码为18位的数字组成,出生日期为第7到第14位
输入说明 :
第一行一个整数n,表示有n个身份证号码 余下的n行,每行一个身份证号码。
n<=100000
输出说明 :
按出生日期从大到小排序后的身份证号,每行一条
解法:希望按出生日期对它们进行从大到小排序,如果有相同日期,则按身份证号码从大到小进行排序。
使用结构体,一部分存储出生日期,一部分存储身份证号码。
#include
using namespace std;
struct node{
string id;
string birth;
};
//找生日更大的
int cmp(struct node a,struct node b){
if(a.birth!=b.birth)
return a.birth>b.birth;
else return a.id>b.id;
}
int main(){
int n;
while(cin>>n)
{
struct node number[n];
int i;
for(i=0;i<n;i++)
{
cin>>number[i].id;
number[i].birth=number[i].id.substr(6,8);
}
sort(number,number+n,cmp);
for(i=0;i<n;i++)
{
cout<<number[i].id<<endl;
}
}
return 0;
}
作者: Turbo时间限制: 1S章节: 模拟
问题描述 :
若一个数(首位不为零)从左向右读与从右向左读都一样,我们就将其称之为回文数。
我们现在需要产生回文数,步骤如下: 给定一个10进制数56,将56加65(即把56从右向左读),得到121是一个回文数。
又如:对于10进制数87: STEP1:87+78 = 165
STEP2:165+561 = 726 STEP3:726+627 = 1353 STEP4:1353+3531 = 4884
在这里的“一步”是指进行了一次N进制的加法,上例最少用了4步得到回文数4884。
写一个程序,给定一个N(2<=N<=10或N=16)进制数M(其中16进制数字为0-9与A-F),求最少经过几步可以得到回文数。
如果在30步以内(包含30步)不可能得到回文数,则输出“Impossible!”输入说明 :
两行,N与M
输出说明 :
如果能在30步以内得到回文数,输出“STEP=xx”(不含引号),其中xx是步数;否则输出一行”Impossible!”(不含引号)
函数fun()逆置数字,主函数累加并判断回文
#include
#include
using namespace std;
int radix, n, sum, flag, a[1001];//定义变量进制数,输入字符串长度,总步数,是否产生回文数,字符串存放的整数数组
string s;
//判断是否是回文数
bool palindromic(int n)
{
for (int i = 1; i <= n / 2; i++)
if (a[i] != a[n - i + 1])
return false;
return true;
}
//两数相加
int add(int n)
{
int c[1001] = { 0 };//定义临时数组,表示两数的和
for (int i = 1; i <= n; i++)//进制数相加
{
c[i] = a[i] + a[n - i + 1] + c[i];//使用同一个数组,进行求回文数
c[i + 1] += c[i] / radix;
c[i] %= radix;
}
if (c[n + 1])//保留进位
n++;
for (int i = n; i >= 1; i--)
{
a[i] = c[i];
}
return n;
}
int main()
{
while(cin>>radix)
{
cin >> s;
n = s.size();
flag=1;
for (int i = 1; i <= n; i++)//将字符串转化为整数数组
{
if (s[i - 1] < 65)
a[i] = s[i - 1] - '0';
else
a[i] = s[i - 1] - 55;
}
while (sum <= 30)
{
if (palindromic(n))
{
cout << "STEP=" << sum << endl;
flag=0;
break;
}
sum++;
n = add(n);
}
if(flag)
cout << "Impossible!" << endl;
}
return 0;
}
作者: Turbo时间限制: 1S章节: 结构体
问题描述 :
新生舞会开始了。n名新生每人有三个属性:姓名、学号、性别。其中,姓名用长度不超过20的仅由大小写字母构成的字符串表示,学号用长度不超过10的仅由数字构成的字符串表示,性别用一个大写字符‘F’或‘M’表示。任意两人的姓名、学号均互不相同。换言之,每个人可被其姓名或学号唯一确定。
输入m对舞伴的信息(姓名或学号),判断他们是否能共舞。两人能共舞的充要条件为两人性别相异。
输入说明 :
第一行一个整数n(2<=n<=1000),表示学生人数。接下来的n行每行依次包含一名新生的姓名、学号、性别,分别用一个空格隔开。
之后的一行是一个整数m(1<=m<=1000),表示询问舞伴的对数。接着的m行每行包含两个舞伴的信息(姓名或学号),保证两个信息不属于同一人,中间用一个空格隔开。输出说明 :
对于每个询问输出一行,如果两人可以共舞,输出一个大写字母‘Y’,否则输出一个大写字母‘N’。
#include
#include
using namespace std;
struct student
{
string name;
string num;
char sex;
};
int main()
{
int n;
while(cin>>n)
{
struct student stu[n];
for(int i=0;i<n;i++)
{
cin>>stu[i].name>>stu[i].num>>stu[i].sex;
}
int m;
cin>>m;
string inf1,inf2;
char sex1,sex2;
for(int j=0;j<m;j++)
{
cin>>inf1>>inf2;
//匹配学号和姓名
for(int i=0;i<n;i++)
{
//cout<
if(stu[i].name==inf1||stu[i].num==inf1)
{
sex1=stu[i].sex;
//cout<
}
if(stu[i].name==inf2||stu[i].num==inf2)
{
sex2=stu[i].sex;
//cout<
}
}
if(sex1==sex2)
cout<<"N"<<endl;
else
cout<<"Y"<<endl;
}
}
}
struct Student{
int sum; //总分
char name[30]; //姓名
}ss[maxn]; //ss[]数组中1每一个元素为一个Student
int cnt=0; //学生数
for(int i=0;i<n;i++){
char tname[30];
scanf("%s",&tname); //输入名字
//名字赋进结构体
strcpy(ss[cnt].name,tname); //ss[i]表示第i个学生,ss[i].name是第i个学生的名字
cnt++;
}
//输入分数score和姓名某某某
for(int j=0;j<cnt;j++){
if(strcmp(ss[j].name,某某某)==0){ //给名字是某某某的同学加上分数score
ss[j].sum+=score;
break;
}
}
sort(ss,ss+cnt,cmp);
bool cmp(Student a,Student b){ //排序标准是学生的sum,从大到小排序
return a.sum>b.sum;
}
注意:这里是要对每次的总分进行排序,即:
第一次用第一次的成绩排名
第n次则用这n次考试的成绩总分排名
题目要求并列时DaDa算并列中的第一,因为我们是从大到小排序,所以从结果中找到Dada后,要往上找,找跟Dada相同分数的同学中第一个的排名。
while(ss[t-1].sum==ss[j].sum){
t--;
}
作者: Turbo时间限制: 1S章节: 结构体
问题描述 :
达达在陶陶的影响下,也对学习慢慢的产生了兴趣。
他在每次考试之后,都会追着老师问,自己在班级的总名次是多少。考试一多,老师也不耐烦了,于是他给了达达所有人的成绩,让他自己去算出自己的排名。
可人太多了,达达也无法立即算出来,于是他想让你帮帮他。输入说明 :
第一行为一个整数N,代表班级的学生总数。 接下来N行,每行一个字符串,代表一个学生的姓名,第一行总是DaDa。
接下来一行一个整数M,代表一共有M次考试。
每次考试有N行,每行有以一个空格分隔的一个正整数S和一个字符串P,代表名字为P的学生在这次考试中得了S分。N <= 100,名字长度不超过30,分数不超过100
输出说明 :
一共M行,每行一个整数,代表达达在班级里的排名,排名是这一次考试过后的所有考试总分排名,如果达达和别人并列,达达总是排在前面。
解法:使用结构体,获取每次的成绩,进行排名
#include
#include
#include
#include
using namespace std;
const int maxn=110;
struct Student{
int sum;
char name[30];
}ss[maxn];
bool cmp(Student a,Student b){
return a.sum>b.sum;
}
int main(){
int n;
scanf("%d",&n);
int cnt=0;
for(int i=0;i<n;i++){
char tname[30];
scanf("%s",&tname);
strcpy(ss[cnt].name,tname);
cnt++;
}
int m;
scanf("%d",&m);
while(m--){
for(int i=0;i<n;i++){
int score;
char tname[30];
scanf("%d %s",&score,&tname);
for(int j=0;j<cnt;j++){
if(strcmp(ss[j].name,tname)==0){
ss[j].sum+=score;
break;
}
}
}
sort(ss,ss+cnt,cmp);
for(int j=0;j<cnt;j++){
if(strcmp(ss[j].name,"DaDa")==0){
int t=j;
while(ss[t-1].sum==ss[j].sum){
t--;
}
cout<<t+1<<endl;
break;
}
}
}
return 0;
}
作者: Turbo时间限制: 1S章节: 结构体
问题描述 :
为了准备一个学生节,组织者在会场的一片矩形区域(可看做是平面直角坐标 系的第一象限)铺上一些矩形地毯。一共有n 张地毯,编号从1
到n。现在将这些地毯按照 编号从小到大的顺序平行于坐标轴先后铺设,后铺的地毯覆盖在前面已经铺好的地毯之上。
地毯铺设完成后,组织者想知道覆盖地面某个点的最上面的那张地毯的编号。注意:在矩形 地毯边界和四个顶点上的点也算被地毯覆盖。输入说明 :
输入共 n+2 行。 第一行,一个整数 n,表示总共有n 张地毯。 接下来的 n 行中,第i+1 行表示编号i
的地毯的信息,包含四个正整数a,b,g,k,每 两个整数之间用一个空格隔开,分别表示铺设地毯的左下角的坐标(a,b)以及地毯在x
轴和y 轴方向的长度。 第 n+2 行包含两个正整数x 和y,表示所求的地面的点的坐标(x,y)。0≤n≤10,000,0≤a, b, g, k≤100,000。
输出说明 :
输出共 1 行,一个整数,表示所求的地毯的编号;若此处没有被地毯覆盖则输出-1。
思路:结构体存储坐标和长度,遍历结构体,找到覆盖给出结点的最大值(即为第几张地毯
#include
#include
struct node
{
int a;
int b;
int c;
int d;
}s[10010];
int main()
{
int n,x,lx,y,ly,x1,y1;
while(scanf("%d",&n)!=EOF)
{
memset(s,0,sizeof(s));
for(int i=1;i<=n;i++)
{
scanf("%d %d %d %d",&x,&y,&lx,&ly);
s[i].a=x;
s[i].b=y;
s[i].c=x+lx;
s[i].d=y+ly;
}
scanf("%d %d",&x1,&y1);
if(x1>100000 || y1>100000)
{
printf("-1\n");
continue;
}
int ans=0;
for(int i=1;i<=n;i++)
{
if(s[i].a<=x1 && s[i].b<=y1 && s[i].c>=x1 && s[i].d>=y1)//满足给定的坐标点,落在已有的地毯上
{
ans=i;//因为地毯先后铺上,只要逐个遍历即可找到最上面的地毯
}
}
if(ans)
printf("%d\n",ans);
else printf("-1\n");
}
return 0;
}
作者: Turbo时间限制: 1S章节: 枚举
问题描述 :
给两组数,各n个。 请调整每组数的排列顺序,使得两组数据相同下标元素对应相乘,然后相加的和最小。要求程序输出这个最小值。
例如两组数分别为:1 3 -5和-2 4 1那么对应乘积取和的最小值应为: (-5) * 4 + 3 * (-2) + 1 * 1 = -25
输入说明 :
第一个行一个数T表示数据组数。后面每组数据,先读入一个n,接下来两行每行n个数,每个数的绝对值小于等于1000。
n<=8,T<=1000输出说明 :
一个数表示答案。
max*min,累加
#include
using namespace std;
bool cmp(int a,int b)
{
return a>b;
}
int main()
{
int n;
while(cin>>n)
{
while(n--)
{
int m;
cin>>m;
int num1[m];
int num2[m];
memset(num1,0,sizeof(num1));
memset(num2,0,sizeof(num2));
long long sum=0;
for(int i=0;i<m;i++)
{
cin>>num1[i];
}
for(int i=0;i<m;i++)
cin>>num2[i];
sort(num1,num1+m);
sort(num2,num2+m,cmp);
for(int i=0;i<m;i++)
{
sum+=num1[i]*num2[i];
}
cout<<sum<<endl;
}
}
return 0;
}
作者: Turbo时间限制: 1S章节: 贪心
问题描述 :
有n个人排队到r个水龙头去打水,他们装满水桶的时间t1、t2…………tn为整数且各不相等,应如何安排他们的打水顺序才能使他们总共花费的时间最少?
输入说明 :
第一行n,r (n<=500,r<=75) 第二行为n个人打水所用的时间Ti (Ti<=100);
输出说明 :
最少的花费时间
思路:
首先理解总时间
时间总和=等待时间+接水时间
贪心思想。先sort()默认从小到大排序。
水龙头,n个人,等于分割成n/m个小数组,每个小数组对应位的数加上上个小数组对应位的数字,就等于,此人的等待时间与接水时间的和,,,最后,所有人的接水时间与等待时间相加,就为所有人花费的时间总和。
因此要让最短的人最先接水
#include
#include
#include
using namespace std;
int main() {
int a[1000],b[0100],n,m;
scanf("%d%d",&n,&m);
int i,sum=0;
for(i=0; i<n; i++)
scanf("%d",&a[i]);
sort(a,a+n);
for(i=0;i<m;i++)
b[i]=a[i];
for(i=m;i<n;i++)
b[i]=b[i-m]+a[i];
for(i=0;i<n;i++)
sum=sum+b[i];
printf("%d\n",sum);
}
enum color_set1 {RED, BLUE, WHITE, BLACK}; // 定义枚举类型color_set1
enum week {Sun, Mon, Tue, Wed, Thu, Fri, Sat}; // 定义枚举类型week
枚举变量的值只能取枚举常量表中所列的值,就是整型数的一个子集。
枚举变量占用内存的大小与整型数相同。
枚举变量只能参与赋值和关系运算以及输出操作,参与运算时用其本身的整数值。
口袋中有红、黄、蓝、白、黑五种颜色的球若干个,每次从口袋中取三个不同颜色的球,统计并输出所有的取法。
分析:由于球只能是五种颜色之一,故可用枚举类型表示球的颜色。设取出的球为i、j、k,根据题意,i、j、k分别可以有五种取值,且i≠j≠k。可以用穷举法,逐个检验每一种可能的组合,从中找出符合要求的组合并输出。
#include
#include
using namespace std;
int main(){
enum color_set {red,yellow,blue,white,black}; //声明枚举类型color
color_set color;
int i,j,k,counter=0,loop; //counter是累计不同颜色的组合数
for(i=red;i<=black;i++) {
for(j=red;j<=black;j++) {
if(i!=j){ //前两个球颜色不同
for(k=red;k<=black;k++)
if(k!=i&&k!=j){ //第三个球不同于前两个,满足要求
counter++;
if((counter)%22==0){ //每屏显示22行
cout<<"请按回车键继续";
cin.get();
}
cout<<setw(15)<<counter;
/*下面输出每种取法,一行为一种取法的三个颜色*/
for(loop=1;loop<=3;loop++){
switch(loop){
case 1: color=(color_set) i; break; //第一个是i
case 2: color=(color_set) j; break; //第二个是j
case 3: color=(color_set) k; break; //第三个是k
}
switch(color){
case red: cout<<setw(15)<<"red"; break;
case yellow:cout<<setw(15)<<"yellow";break;
case blue: cout<<setw(15)<<"blue"; break;
case white: cout<<setw(15)<<"white"; break;
case black: cout<<setw(15)<<"black"; break;
}
}
cout<<endl; //输出一种取法后换行
}
}
}
}
cout<<"共有:"<<counter<<"种取法"<<endl;
return 0;
}
以下分析转载注明出处:http://blog.csdn.net/u011400953
【分析】:这道题目可以用最暴力的方法:枚举串长度,枚举串的起始位置,将扫到的串次序加入,并记录相关信息。经高人指点,用c++STL实现
【自己总结的相关信息】:(可能有不完善或错误的地方)
①:pair
now;定义path类型<类似于map>,包含first,second,对应pair中第一维变量与第二维变量②:s.substr(j,i),将string类型的字符串s从第j位开始取i位
③:map
::iterator
i;map类型的正向迭代器i,i为名称,map::reverse_iterator i ,map类型的反向迭代器
,rbegin()为反向迭代器扫描的第一位,而begin()为正向迭代器扫描的第一位,rend(),end()同理。④:迭代器变量调取<以③中迭代器为例>i->first表示map类型的迭代器i的第一维变量
⑤:map类型的数据排序:将要排序的元素放到最后一维,然后 sort(g.begin(),g.end(),cmp);
⑥:字典序排序的cmp表示法:return a
⑦:multimap类型,可重映射,即第一维可重复,在本题中第一维存字符串
⑧:map类型几个操作:t.find(k);<查找一个元素,若没找到则返回指向map末尾的迭代器,复杂度O(logN),因此可以用t.end()=t.find(k)来作为没有找到的标志,注意:返回的是个迭代器,因此应开迭代器来存>,t.insert(now);插入元素now
第一种解法
/*
ID:csyzcyj1
PROG:contact
LANG:C++
*/
#include
#include
#include
#include
#include
#include
#include
using namespace std;
map<string,int> f;
multimap<int,string> t;
vector<string> g;
int a,b,n;
string s,in;
int num=0,last=0;
bool cmp(const string &a,const string &b)
{
if(a.size()!=b.size())
return a.size()<b.size();//先按串的长度排序
return a<b;//再按字典序排
}
int main()
{
freopen("contact.in","r",stdin);
freopen("contact.out","w",stdout);
scanf("%d%d%d",&a,&b,&n);
while(cin>>in) s+=in;//读入<可能有多个串在多行>
b=min((int)s.size(),b); //若不加可能会越界
for(int i=a;i<=b;i++)//枚举长度
for(int j=0;j<s.size()-i+1;j++)//枚举起点
{
pair<string,int> now;//记录子串
now.first=s.substr(j,i);//first.second表示调取pair中第一维变量与第二维变量
now.second=1;
map<string,int>::iterator it;//正向迭代器,it为名称
it=f.find(now.first);//查找一个元素,若没找到则返回指向map末尾的迭代器,复杂度O(logN)
if(it!=f.end()) it->second++;//若找到了
else f.insert(now);//插入元素
}
for(map<string,int>::iterator i=f.begin();i!=f.end();i++)//创建一个迭代器,初始状态为指向f的首元素 map类型,begin()为F正向迭代的第一位>
t.insert(pair<int,string>(i->second,i->first));//将旧的f中的first元素和second元素调换并存入t中 multimap类型,可重映射,即第一维可重复>
for(map<int,string>::reverse_iterator i=t.rbegin();i!=t.rend();i++)//< reverse_iterator -> 反向迭代器 ,rbegin()为t反向迭代的第一位>
{
if(i->first==last) //若当前串的出现次数与上一个的出现次数一样
g.push_back(i->second);
else
{
num++;//表示出现了重复次数的串已统计完
if(last!=0)//判断是否为初始情况
{
sort(g.begin(),g.end(),cmp);//把将要输出的串排序
for(int i=0;i<g.size()-1;i++)
{
cout<<g[i];
if((i+1)%6==0) cout<<endl;//每行只能输出6个
else cout<<" ";
}
cout<<g[g.size()-1]<<endl;//最后一个单独输出
g.clear();//清空输出序列
}
if(num>n) break;//输出完了
cout<<i->first<<endl;//输出出现的次数
g.push_back(i->second);//并将该串加入输出序列
last=i->first;//打标记:用于查有相同出现次数的串
}
}
if(num<=n)//可能出现下面注释的情况
{
sort(g.begin(),g.end(),cmp);
for(int i=0;i<g.size()-1;i++)
{
cout<<g[i];
if((i+1)%6==0) cout<<endl;//每行只能输出6个
else cout<<" ";
}
cout<<g[g.size()-1]<<endl;
g.clear();
}
return 0;
}
/*
注释1:
若不加那一段,
那么就会输出这个 实际:
480 480
1 1
479 479
11 11
478 478
111 111
477 477
1111 1111
476 476
11111 11111
475 475
111111 111111
474 474
1111111 1111111
473 473
11111111 11111111
472 472
111111111 111111111
471 471
1111111111 1111111111
470 470
11111111111 11111111111
469 469
111111111111
*/
第二种解法
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define lowbit(a) (a&(-a))
#define _mid(a,b) ((a+b)/2)
#define _mem(a,b) memset(a,0,(b+3)<<2)
#define fori(a) for(int i=0;i<a;i++)
#define forj(a) for(int j=0;j<a;j++)
#define ifor(a) for(int i=1;i<=a;i++)
#define jfor(a) for(int j=1;j<=a;j++)
#define mem(a,b) memset(a,b,sizeof(a))
#define IN freopen("in.txt","r",stdin)
#define OUT freopen("out.txt","w",stdout)
#define IO do{\
ios::sync_with_stdio(false);\
cin.tie(0);\
cout.tie(0);}while(0)
#define mp(a,b) make_pair(a,b)
#define debug(a) cout <<(a) << endl
using namespace std;
typedef long long ll;
const int maxn = 2*1e2+9;
const int INF = 0x3f3f3f3f;
const int inf = 0x3f;
const double EPS = 1e-7;
const double Pi = acos(-1);
const int MOD = 1e9+7;
char str[2000005];
pair<string,int>PAIR;
struct cmp {
bool operator ()(pair<string,int>&a,pair<string,int>&b) {
if(a.second != b.second)
return a.second<b.second;
if(a.first.size() != b.first.size())
return a.first.size() > b.first.size();
return a.first > b.first;
}
};
string s;
map<string,int>qqq;
priority_queue<pair<string,int>,vector<pair<string,int> >,cmp>prique;
int main() {
//IN;
//OUT;
int x,b,n;
char c;
int cn = 0;
cin >> x >> b >>n;
while(~(c=getchar()))
if(c!='\n')
str[cn++] = c;
s = str;
for(int i=0; i+x<=s.size(); i++)
for(int j=x; j<=b&&j+i<=s.size(); j++)
qqq[s.substr(i,j)]++;
for(auto i:qqq)
prique.push(i);
int buf = -1;
int cnt = 0;
int cnr = 0;
bool flag = false;
while(!prique.empty()) {
if(buf!=prique.top().second){
if(cnr == n)
break;
buf = prique.top().second;
cout <<(flag?"\n":"")<<buf<<endl;
cnt = 0;
flag = true;
cnr++;
}
if(cnt==6)
cout << endl,cnt = 0;
if(cnt)
cout <<" ";
cnt++;
cout << prique.top().first;
prique.pop();
}
return 0;
}
作者: Turbo时间限制: 1S章节: 贪心
问题描述 :
回文串,是一种特殊的字符串,它从左往右读和从右往左读是一样的。小龙龙认为回文串才是完美的。现在给你一个串,它不一定是回文的,请你计算最少的交换次数使得该串变成一个完美的回文串。
交换的定义是:交换两个相邻的字符 例如mamad 第一次交换 ad : mamda 第二次交换 md : madma
第三次交换 ma : madam (回文!完美!)输入说明 :
第一行是一个整数N,表示接下来的字符串的长度(N <= 8000) 第二行是一个字符串,长度为N.只包含小写字母
输出说明 :
如果可能,输出最少的交换次数。 否则输出Impossible
解法:
impossible的情况:如果有一个字符出现的次数是奇数次数,而且n是偶数,那么不可能构成回文,如果n是奇数,但是已经有一个字符出现的次数是奇数次数了,那么如果又有一个字符是奇数次数,就不可能构成回文。
注意:若n是奇数,计算中间那个字符交换的次数的时候,不需要模拟把这个数移动到中间去,因为移动到中间的话——假设有一对数都在左边或者都在右边,那么交换成回文的时候就要经过中间,就会每次多加了1,而这个1是没有必要的,因为可以所有的回文移动完了之后再把这个独立的数移动过去,才能保证交换次数最少。
#include
using namespace std;
char str[8005];
int main() {
int n, r, ans = 0, temp = 0;
scanf("%d%s", &n, str);
r = n - 1;//r指向字符串需要交换的末尾下标
for (int i = 0; i < n / 2; i++) {//i指针从头遍历到中间字符
for (int j = r; j >= i; j--) {//j指针从后面往前一直到i寻找和str[i]相同的str[j]
if (j != i) {
if (str[i] == str[j]) {
for (int k = j; k < r; k++)//把str[j]换到str[r]处
swap(str[k], str[k + 1]);
ans += r - j;//统计交换次数
r--;//往前推进
break;
}
}
else {//如果找不到相同的
if (!(n & 1) || temp) {//impossible的两种情况, temp表示出现奇数次的字符。
printf("Impossible\n");//n&1,与运算,可以判断n是否为偶数,,如果是偶数,n&1返回0;否则返回1,为奇数。
return 0;
}
temp = 1;
ans += n / 2 - i;//移动到中间需要的交换次数(距离即为交换次数),不需要现在交换过去,最后交换
}
}
}
printf("%d\n", ans);
return 0;
}
作者: Turbo时间限制: 1S章节: 贪心
问题描述 :
元旦快到了,校学生会让乐乐负责新年晚会的纪念品发放工作。为使得参加晚会的同学所获得的纪念品价值
相对均衡,他要把购来的纪念品根据价格进行分组,但每组最多只能包括两件纪念品,并且每组纪念品的价格之和不能超过一个给定的整数。为了保证在尽量短的时
间内发完所有纪念品,乐乐希望分组的数目最少。 你的任务是写一个程序,找出所有分组方案中分组数最少的一种,输出最少的分组数目。输入说明 :
输入包含n+2行: 第1行包括一个整数w,为每组纪念品价格之和的上限。 第2行为一个整数n,表示购来的纪念品的总件数。
第3~n+2行每行包含一个正整数pi (5 <= pi <= w),表示所对应纪念品的价格。1 <= n <= 30000, 80 <= w <= 200
输出说明 :
输出仅一行,包含一个整数,即最少的分组数目。