C++题目求解

一、有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少?#include <stdio.h>
int main(){
int month,temp1,temp2;
month=temp1=temp2=2;
printf("第1个月兔子数量为2\n");
printf("第2个月兔子数量为2\n");
while(month<20){
month++;
int temp=temp2;
temp2=temp1+temp2;
temp1=temp;
printf("第%d个月兔子数量为%d\n",month,temp2);
}
return 0;
}
二、判断101-200之间有多少个素数,并输出所有素数#include <stdio.h>
#define bool int
#define true 1
#define false 0
bool isPrime(int num){
for(int i=2;i*i<=num;i++)
if(num%i==0)
return false;
return true;
}
int main(){
int sum=0;
for(int i=101;i<=200;i++)
if(isPrime(i)){
sum++;
printf("%d是素数\n",i);
}
printf("自101到200之间一共有%d个素数\n",sum);
return 0;
}
三、打印出所有的“水仙花数”,所谓“水仙花数”是指一个三位数,其各位数字立方和等于该数本身#include <stdio.h>
#define bool int
#define true 1
#define false 0
bool isTure(int num){
int h=num/100;
int t=(num-h*100)/10;
int s=num%10;
if(s*s*s+t*t*t+h*h*h==num) return true;
return false;
}
int main(){
for(int i=100;i<=999;i++)
if(isTure(i)) printf("水仙花数:%d\n",i);
return 0;
}
四、将一个正整数分解质因数从最小质数2开始,若当前剩余数字能整除该候选因数,则当前数字等于当前数字除以该质因数,并输出,否则因数加一#include <stdio.h>
#define bool int
#define true 1
#define false 0
bool isPrime(int num){
for(int i=2;i*i<=num;i++)
if(num%i==0) return false;
return true;
}
int main(){
int num;int d=2;
scanf("%d",&num);
while(num>1){
if(num%d==0&&isPrime(d)){
num=num/d;
printf("%d",d);
if(num>1)
printf("*");
}
else d++;
}
return 0;
}
五、利用条件运算符的嵌套:学习成绩>=90分的同学用A表示,60-89分之间的用B表示,60分以下的用C表示#include <stdio.h>
int main(){
int mark;
scanf("%d",&mark);
(mark>=90)?printf("A\n"):((mark>=60)?printf("B\n"):printf("C\n"));
return 0;
}
六、输入两个正整数m和n,求其最大公约数和最小公倍数最大公因数使用辗除法:假设用f(x, y)表示x,y的最大公约数,则有f(x, y)=f(y, x%y)当x%y等于0时代表y就是原始两个数的最大公因数算法步骤:若n不等于0则进行2,否则3令n等于m%n,令m等于原先的n,返回2进行判断输出m,程序结束最小公倍数使用两数之积除以最大公因数#include <stdio.h>
/*最大公因数计算函数*/
int getGCD(int m,int n){
while(n!=0){
int temp=m%n;
m=n;
n=temp;
}
return m;
}
/*最小公倍数计算函数*/
int getLCM(int n1,int n2){return n1*n2/getGCD(n1,n2);}
int main(){
int n1,n2;
scanf("%d %d",&n1,&n2);
printf("最大公因数为:%d\n",getGCD(n1,n2));
printf("最小公倍数为:%d\n",getLCM(n1,n2));
return 0;
}
七、输入一行字符,分别统计出其中英文字母、空格、数字和其它字符的个数#include <stdio.h>
int main(){
int cNum,bNum,mNum,elseNum;
char c;
cNum=bNum=mNum=elseNum=0;
while(){
c=getchar();
if(c=='\n') break;
if((c>='a'&&c<='z')
(c>='A'&&c<='Z'))
cNum++;
else if(c==' ')
bNum++;
else if(c>='0'&&c<='9')
mNum++;
else
elseNum++;
}
printf("字母个数为:%d\n",cNum);
printf("空格个数为:%d\n",bNum);
printf("数字个数为:%d\n",mNum);
printf("其它字符个数为:%d\n",elseNum);
return 0;
}
八、求s=a+aa+aaa+aaaa+aa…a的值,其中a是一个数字,a与a重复最大次数由用户输入注意sum使用float,不然结果会错误#include <stdio.h>
#include <math.h>
int main(){
int num,round;
float sum=0;
scanf("%d %d",&num,&round);
for(int i=0;i<round;i++)
for(int j=0;j<=i;j++)
sum+=num*pow(10,j);
printf("%.0f",sum);
return 0;
}
九、一个数如果恰好等于它的因子之和,这个数就称为“完数”。例如6=1+2+3。编程找出1000以内的所有完数#include <stdio.h>
int main(){
for(int i=1;i<=1000;i++){
int sum=0;
for(int j=1;j<i;j++)
if(i%j==0)
sum+=j;
if(sum==i)
printf("%d\n",i);
}
return 0;
}
十、一球从100米高度自由落下,每次落地后反跳回原高度的一半;再落下,求它在第10次落地时,共经过多少米?第10次反弹多高?#include <stdio.h>
int main(){
double oriHeight=100;
double totalHeight=0;
for(int i=0;i<10;i++){
totalHeight+=oriHeight;
if(i==9)
printf("第10次落地共经过%.10lf米\n",totalHeight);
oriHeight=oriHeight/2;
if(i==9)
printf("第10次反弹%.10lf米\n",oriHeight);
totalHeight+=oriHeight;
}
return 0;
}
十一、一只猴子摘了N个桃子第一天吃了一半又多吃了一个,第二天又吃了余下的一半又多吃了一个,到第十天的时候发现还有一个。求第一天桃子数量。#include <stdio.h>
int main(){
int num=1;
for(int i=1;i<10;i++)
num=(num+1)*2;
printf("第一天的桃子数量:%d",num);
}
十二、使用牛顿迭代法求一个数字的正平方根牛顿迭代法:本质是求f(x)=0的根,迭代方式为所以再求一个数A的平方根的时候,f(x)=x2-A=0,而不是f(x)=x2。#include <stdio.h>
#include<math.h>
#define Epsilon 1.0E-9 /*控制精度*/
int main(){
double num,x0,x1;
scanf("%lf",&num);
x0=num/2;
x1=(num/x0+x0)/2;
while(fabs(x1-x0)>=Epsilon){
x0=x1;
x1=(num/x0+x0)/2;
}
printf("%lf的平方根为:%.3lf",num,x1);
}
十三、牛顿迭代法求方程 2x3-4x2+3x-6 的一个根#include <stdio.h>
#include<math.h>
#define Epsilon 1.0E-6 /*控制解的精度*/
int main(){
float x0,x1=1.5;
x1=(4*x0*x0*x0-4*x0*x0+6)/(6*x0*x0-8*x0+3);
while(fabs(x1-x0)>=Epsilon){
x0=x1;
x1=(4*x0*x0*x0-4*x0*x0+6)/(6*x0*x0-8*x0+3);
}
printf("方程的根为%.3f\n",x1);
return 0;
}
十四、输入数字n,然后输入一个n位的数字num,判断num是否是回文数#include <stdio.h>
#include<math.h>
int main(){
int len;
double sum,rsum;sum=rsum=0;
scanf("%d",&len);
char num[len];
for(int i=0;i<len;i++){
num[i]=getchar();
while(num[i]<'0'
num[i]>'9')
num[i]=getchar();
sum+=(num[i]-48)*pow(10,len-1-i);
}
for(int i=len-1;i>=0;i--)
rsum+=(num[i]-48)*pow(10,i);
if(sum==rsum)
printf("%.0lf是回文数\n",sum);
else
printf("%.0lf不是回文数\n",sum);
}
十五、求100之内的素数#include <stdio.h>
#define bool int
#define true 1
#define false 0
bool isPrime(int num){
if(num<=1) return false;
for(int i=2;i*i<=num;i++)
if(num%i==0) return false;
return true;
}
int main(){
for(int i=1;i<=100;i++)
if(isPrime(i)) printf("%d是素数\n",i);
return 0;
}
十六、画出心形图案,心形线公式(x2+y2-1)3-x2y3=0,心形内部(包括边界)公式小于等于零#include <stdio.h>
int main() {
for(float y = 1.5; y > -1.5; y -= 0.1){
for(float x = -1.5; x < 1.5; x += 0.05){
float a = x * x + y * y - 1;
putchar(a * a * a - x * x * y * y * y <= 0.0 ? '*' : ' ');
}
putchar('\n');
}
}
结果:十七、字符串去特定字符题目链接,注意:当使用gets函数时,函数会读取换行符,并停止函数,所以不需要单独一个getchar来处理换行符,但当使用scanf时,scanf会将换行符留给下次操作处理,所以当使用scanf时需要加一个getchar函数来处理换行符。另外输出字符时,需要判断是否已经到了‘\0’空字符,也就是字符串结尾,如果是的话则跳出循环。#include <stdio.h>
int main(){
char c,str[1000];
gets(str);
c=getchar();
for(int i=0;i<1000;i++)
if(str[i]==c)
continue;
else if(str[i]!=c&&str[i]!='\0')
printf("%c",str[i]);
else
break;
return 0;
}
十八、字符串连接,不用strcat 函数#include <stdio.h>
static char result[2000];
char* myStrCat(char* str1,char* str2){
int i=0,j=0;
while(str1[j]!='\0')
result[i++]=str1[j++];
j=0;
while(str2[j]!='\0')
result[i++]=str2[j++];
result[i]='\0';
return result;
}
int main(){
char str1[1000],str2[1000];
gets(str1);gets(str2);
char* p=myStrCat(str1,str2);
printf("%s\n",p);
return 0;
}
十九、输入一个字符串,长度小于等于200,然后将输出按字符顺序升序排序后的字符串#include <stdio.h>
#include <string.h>
static char str[200];
void sort(int low, int high){
if (low < high){
int i = low;
int j = high;
int k = str[low];
while (i < j){
while(i < j && str[j] >= k) j--;
if(i < j) str[i++] = str[j];
while(i < j && str[i] < k) i++;
if(i < j) str[j--] = str[i];
}
str[i] = k;
sort(low, i - 1);
sort(i + 1, high);
}
}
int main(){
gets(str);
printf("原字符串:%s\n",str);
sort(0,strlen(str)-1);
printf("排序后字符串:%s\n",str);
return 0;
}
结果:dadASAASAsasa!@!:SQS
原字符串:dadASAASAsasa!@!:SQS
排序后字符串:!!:@AAAAQSSSSaaaddss
二十、已知不等式1!+ 2!+… + m!<n, 对用户指定的n值,输出满足该不等式m的最大整数解TIP:使用一个变量记录第i次计算阶乘时第i-1次的阶乘结果,能够缩短计算时间,减少运行时间#include <stdio.h>
int main(){
int n,m,sum,temp;
m=sum=0;temp=1;
scanf("%d",&n);
for(m=1;;m++){
temp*=m;
sum+=temp;
if(sum>=n)
break;
}
printf("m:%d\n",m-1);
return 0;
}
二十一、用小于等于n元去买100只鸡,A鸡5元/只,B鸡3元/只,C鸡1/3元/只,分别记为x只,y只,z只,求解x,y,z所有可能解,对于每组输入,请输出x,y,z所有可行解,按照x,y,z依次增大的顺序输出。#include <stdio.h>
int main(){
int x,y,z,n;
scanf("%d",&n);
for(x=0; x<=n/5; x++)
for(y=0; y<=n/3; y++)
for(z=0; z<=n*3; z++)
if(x+y+z==100&&5*x+3*y+z/3.0<=n)
printf("x=%d,y=%d,z=%d\n",x,y,z);
return 0;
}
二十二、一个百万富翁遇到一个陌生人,陌生人找他谈了一个换钱的计划。该计划如下:我每天给你10万元,你第一天给我1分钱,第二天2分钱,第三天4分钱……这样交换 30 天后,百万富翁交出了多少钱?陌生人交出了多少钱?#include <stdio.h>
int main(){
long sum=0;
long money=1;
for(int i=0; i<30; i++){
sum+=money;
money*=2;
}
printf("百万富翁交出的钱:300万元\n");
printf("陌生人交出的钱:%f万元\n",sum/1000000.0);
return 0;
}
二十三、输入一个数n,然后输入n个各不相同的数,调换数组中最大和最小的两个数,然后输出#include <stdio.h>
int main(){
int n,min,max,temp;
scanf("%d",&n);
int arr[n];
min=max=0;
for(int i=0; i<n; i++){
scanf("%d",&arr[i]);
if(arr[min]>arr[i]) min=i;
if(arr[max]<arr[i]) max=i;
}
temp=arr[min];
arr[min]=arr[max];
arr[max]=temp;
for(int i=0; i<n; i++)
if(i!=n-1)
printf("%d ",arr[i]);
else
printf("%d\n",arr[i]);
return 0;
}
二十四、给定三角形的三条边a、b、c。判断是否能组成三角形,若能组成则判断该三角形类型(锐角、直角、钝角)思路:使用勾股定理:若最大边的平方大于两小边平方和,则是钝角三角形;若最大边的平方等于两小边平方和,则是直角三角形;若最大边的平方小于两小边平方和,则是锐角三角形。#include <stdio.h>
void judge(int a, int b, int c){
int temp=a;
a=a>b?a:b;
b=a==b?temp:b;
temp=a;
a=a>c?a:c;
c=a==c?temp:c;
if(a>=(b+c))
printf("无法组成三角形\n");
else if(a*a>(b*b+c*c))
printf("该三角形是钝角三角形\n");
else if(a*a==(b*b+c*c)) printf("该三角形是直角三角形\n");
else
printf("该三角形是锐角三角形\n");
}
int main(){
int a,b,c;
scanf("%d %d %d",&a,&b,&c);
judge(a, b, c);
return 0;
}
二十五、输入两个整数a和b,计算a+b的和。注意此题是多组测试数据,以在Windows下,用户按下CTRL+Z(会看到一个^Z字符)再按下回车(可能需要重复多次),表示输入结束;Linux/Unix下使用CTRL+D表示输入结束。思路:scanf()函数返回值分为3种:返回正整数。表示正确输入参数的个数返回整数0。表示用户的输入不匹配,无法正确输入任何值返回-1。表示输入流已经结束。在Windows下,用户按下CTRL+Z(会看到一个^Z字符)再按下回车(可能需要重复多次),就表示输入结束;Linux/Unix下使用CTRL+D表示输入结束#include<stdio.h>
int main(){
int a,b;
while(scanf("%d%d", &a, &b)!=-1) printf("%d\n",a+b);
return 0;
}
二十六、有一头母牛,它每年年初生一头小母牛。每头小母牛从第四个年头开始,每年年初也生一头小母牛。请编程实现在第n年的时候,共有多少头母牛?思路:递推数列,类似于斐波那契额数列。前四年每一年的牛数量等于年数,四年以后从第五年开始第i年等于第n-1年加第n-3年。#include<stdio.h>
int arr[55];
void cal(){
for(int i=0; i<55; i++)
if(i<=4)
arr[i]=i;
else
arr[i]=arr[i-1]+arr[i-3];
}
int main(){
cal();
int temp;
while(1){
scanf("%d",&temp);
if(!temp)
break;
printf("%d\n",arr[temp]);
}
return 0;
}
二十七,给定一元二次方程的a,b,c,求解ax2+bx+c=0的解。当b2-4ac小于0时,求出其虚数解。(结果的实部和虚部都保留3位小数)解析:用bool型变量flag表明Δ是否小于0.若小于零,则最后输出的虚部后面需要加上i#include<stdio.h>
#include<math.h>
#include<stdbool.h>
int main(void){
int a,b,c;
bool flag=true;
scanf("%d %d %d",&a,&b,&c);
double RP=(double)(-b)/(2*a);
if(b*b-4*a*c<0) flag=false;
double IP=(double)sqrt(fabs(b*b-4*a*c))/(2*a);
if(flag)
printf("%.3lf %.3lf\n",RP+IP,RP-IP);
else
printf("x1=%.3lf+%.3lfi x2=%.3lf-%.3lfi\n",RP,IP,RP,IP);
return 0;
}
测试结果:4 1 1
x1=-0.125+0.484i x2=-0.125-0.484i
二十八、输入10个整数,将其中最小的数与第一个数对换,把最大的数与最后一个数对换。写三个函数;①输入10个数;②进行处理;③输出10个数。注意:最后在交换元素时,可能在交换第0元素与最小元素时最大元素索引会改变,因为最大元素可能在第0号元素。#include<stdio.h>
int arr[10];
int min=0;max=0,minIndex=-1,maxIndex=-1;
void getNum(){
for(int i=0;i<10;i++){
scanf("%d",&arr[i]);
if(minIndex==-1) {min=arr[i]; minIndex=i; max=arr[i]; maxIndex=i;}
else{
if(arr[i]<min)
{min=arr[i];
minIndex=i;}
if(arr[i]>max)
{max=arr[i];
maxIndex=i;}
}
}
}
void cal(){
int temp1=arr[0],temp2=arr[9];
arr[0]=min;
arr[minIndex]=temp1;
if(maxIndex==0) maxIndex=minIndex;
arr[9]=arr[maxIndex];
arr[maxIndex]=temp2;
}
void show(){
for(int i=0;i<10;i++)
printf("%d ",arr[i]);
}
int main(void){
getNum();
cal();
show();
return 0;
}
二十九、有一字符串,包含n个字符。写一函数,将此字符串中从第m个字符开始的全部字符复制成为另一个字符串。注意:使用getchar()吸收gets()函数调用之前的换行符,因为gets()不会忽略前面的空白#include<stdio.h>
char newStr[100];
void cpy(char* str, int n, int m){
int index=0;
for(int i=m-1;i<n;i++)
newStr[index++]=str[i];
newStr[index]='\0';
}
int main(void){
int n,m;
scanf("%d",&n);
getchar();
char str[n+1];
gets(str);
scanf("%d",&m);
cpy(str,n,m);
printf("%s\n",newStr);
return 0;
}
三十、定义一个结构体变量(包括年、月、日)。计算该日在本年中是第几天,注意闰年问题。样例输入:2000 12 31样例输出:366#include<stdio.h>
int days[12]={31,28,31,30,31,30,31,31,30,31,30,31};
struct date{
int year;
int month;
int day;
};
int isLeapYear(int year){
if(year%400==0
(year%4==0&&year%100!=0))
return 1;
return 0;
}
void cal(struct date myDate){
int result=0;
if(isLeapYear(myDate.year)) days[1]=29;
for(int i=0;i<myDate.month-1;i++)
result+=days[i];
result+=myDate.day;
printf("%d\n",result);
}
int main(void){
struct date myDate;
scanf("%d %d %d",&myDate.year,&myDate.month,&myDate.day);
cal(myDate);
return 0;
}
三十一、现有有N个学生的数据记录,每个记录包括学号、姓名、三科成绩。 编写一个函数input,用来输入一个学生的数据记录。 编写一个函数print,打印一个学生的数据记录。 在主函数调用这两个函数,读取N条记录输入,再按要求输出。 N<100。样例输入2
a100 clang 70 80 90
b200 dotcpp 90 85 75
样例输出a100,clang,70,80,90
b200,dotcpp,90,85,75
#include<stdio.h>
struct student{
char id[100];
char name[100];
int mark1;
int mark2;
int mark3;
};
void input(struct student* p){
scanf("%s %s %d %d %d",p->id,p->name,&(p->mark1),&(p->mark2),&(p->mark3));
}
void print(struct student* p){
printf("%s,%s,%d,%d,%d\n",p->id,p->name,p->mark1,p->mark2,p->mark3);
}
int main(void){
int n;
scanf("%d",&n);
struct student arr[n];
getchar();
for(int i=0;i<n;i++){
input(&arr[i]);
getchar();
}
for(int i=0;i<n;i++){
print(&arr[i]);
}
return 0;
}
三十二、已有a、b两个链表,每个链表中的结点包括学号、成绩。要求把两个链表合并,按学号升序排列。第一行,a、b两个链表元素的数量N、M,用空格隔开。 接下来N行是a的数据 然后M行是b的数据 每行数据由学号和成绩两部分组成。题目OJ地址样例输入2 3
5 100
6 89
3 82
4 95
2 10
样例输出2 10
3 82
4 95
5 100
6 89
#include <stdio.h>
#include <stdlib.h>
typedef struct Stu{
int id;
int score;
struct Stu* next;
}Stu;
Stu* create(int n){
Stu* head = malloc(sizeof(Stu));
head->id=-1;
head->score=-1;
head->next=NULL;
for(int i=0;i<n;i++){
Stu* newStu=malloc(sizeof(Stu));
scanf("%d %d",&newStu->id,&newStu->score);
newStu->next=NULL;
if(head->id==-1)
head=newStu;
else
{newStu->next=head;
head=newStu;}
}
return head;
}
Stu* merge(Stu* s1, Stu* s2){
Stu* p=s1;
while(p->next!=NULL)
p=p->next;
p->next=s2;
return s1;
}
void sort(Stu* s){
for(Stu* i=s;i!=NULL;i=i->next)
for(Stu* j=i;j!=NULL;j=j->next){
if(i->id>j->id){
int idTemp=i->id;
int scoreTemp=i->score;
i->id=j->id;
i->score=j->score;
j->id=idTemp;
j->score=scoreTemp;
}
}
}
void print(Stu* s){
while(s!=NULL){
printf("%d %d\n",s->id,s->score);
s=s->next;
}
}
int main(){
int N, M;
scanf("%d %d",&N,&M);
Stu* students1=create(N);
Stu* students2=create(M);
students1=merge(students1, students2);
sort(students1);
print(students1);
return 0;
}
三十三、数字整除 OJ网址定理:把一个至少两位的正整数的个位数字去掉,再从余下的数中减去个位数的5倍。当且仅当差是17的倍数时,原数也是17的倍数。例如,34是17的倍数,因为3-20=-17是17的倍数;201不是17的倍数,因为20-5=15不是17的倍数。输入一个正整数n,你的任务是判断它是否是17的倍数。思路:对于大整数,不要将其完全读入一个字符串中,而是模拟除法,一位一位读取,没读取一位就计算其与17的余数样例输入34
201
2098765413
1717171717171717171717171717171717171717171717171718
0
样例输出1
0
1
0
#include<stdio.h>
int main(){
int num=0;
char c;
c=getchar();
while(1){
while(c!='\n'){
num=num*10+c-'0';
num%=17;
c=getchar();
}
if(num==0)
printf("1\n");
else
printf("0\n");
num=0;
c=getchar();
if(c=='0')
return 0;
}
return 0;
}
三十四、循环节描述:https://www.dotcpp.com/oj/problem1101.html参考:https://blog.dotcpp.com/a/61187#include <iostream>
#include <cstring>
using namespace std;
int k;
void mul(int* a,int b,int* c){//高精低乘
for(int i=0;i<=k;i++)c[i]=0;
int cou=0;
for(int i=1;i<=k;i++){
c[i]=a[i]*b+cou;
cou=c[i]/10;
c[i]%=10;
}
}
void mult(int *a,int* b,int* c){//高精高乘
for(int i=0;i<=k;i++)c[i]=0;
for(int i=1;i<=k;i++)
for(int j=1;i+j-1<=k;j++)
c[j+i-1]+=a[j]*b[i];
int cou=0;int go=0;
for(int i=1;i<=k;i++){
go=c[i]+cou;
c[i]=go%10;
cou=go/10;
}
}
int main(){
string s;
cin>>s>>k;//读入数据,建议用string类型读入,使用int会WA
//将字符串转换成整型数组存储
int ss=s.size();
int n[ss+1],//存储n
n0[k+1],//只取n的后k位,该数组用于比较进行每一位的循环匹配
c0[k+1],//每次累乘的结果
c1[k+1],//每次累乘的乘数一
c2[k+1],//每次累乘的乘数二
c3[k+1];//n的循环节次幂再乘以n存放于该数组再与n0进行匹配,即c3=c0*n
//将字符串转换成整型数组,注意顺序颠倒
for(int i=0;i<ss;i++)
n[ss-i]=s[i]-'0';
//对数组进行初始化
for(int i=1;i<=k;i++)
if(i<=ss)
c2[i]=c1[i]=c0[i]=n0[i]=n[i];
else
c2[i]=c1[i]=c0[i]=n0[i]=0;
//存储循环节的数组nowc,其nowcc是辅助数组
int nowc[101],nowcc[101];
memset(nowc,0,sizeof(nowc));
memset(nowcc,0,sizeof(nowcc));
nowc[1]=nowcc[1]=1;
for(int i=1;i<=k;i++){
for(int j=1;j<=11;j++){
mult(c0,n,c3);//n的已计算出的循环节次幂存储在c0,再乘以n得到要匹配的值
if(c3[i]==n0[i]){
mul(nowc,j,nowcc);//更行循环节
copy(nowcc,nowcc+101,nowc);
copy(c0,c0+k+1,c2);//更新乘数二
break;
}
else if(j==11){//没有循环节
cout<<-1<<endl;
return 0;
}
//累乘
mult(c1,c2,c0);
copy(c0,c0+k+1,c1);
}
}
//去除前导0,输出答案
int ii;
for(ii=100;ii>=1&&nowc[ii]==0;ii--);
while(ii>0)
cout<<nowcc[ii--];
return 0;
}
三十五、守望者的逃离描述:https://www.dotcpp.com/oj/problem1108.html思路:贪心#include<iostream>
using namespace std;
int main(){
int m,s,t,copy,flash=0,dis=0;
cin>>m>>s>>t;
copy=t;
while((t--)!=0){
/*闪现距离*/
if(m>=10){
flash+=60;
m-=10;
}
else
m+=4;
/*跑步距离*/
dis+=17;
/*
当前这一秒结束时,
比较跑步距离与闪现距离相对大小,
将跑步距离设为较大的
*/
if(flash>dis)
dis=flash;
if(dis>=s){
cout<<"Yes"<<endl<<copy-t<<endl;
return 0;
}
}
cout<<"No"<<endl<<dis<<endl;
return 0;
}
三十六、使用纸和剪刀,通过以下方式切出两个面以形成圆柱体:水平切纸(平行于短边)以得到两个矩形部分。从第一部分开始,切出一个最大半径的圆。 圆圈将形成圆柱体的底部。将第二部分卷起来,使其周长与圆的周长相等,然后将卷的一端连接到圆上。 请注意,卷筒可能会有一些重叠的部分,以便获得所需的周长。在给定纸张尺寸的情况下,计算出可以使用上述步骤构造的最大量的滚筒?结果保留3位小数OJ地址:https://www.dotcpp.com/oj/problem1111.html注意:保留几位小数使用#include <iomanip>头文件,并在cout中使用fixed<<setprecision(3)控制小数点后三位小数,如果不加fixed,则会保留三位有效数字思路:#include<iostream>
#include<algorithm>
#include <iomanip>
#define pi 3.141592653589793238
using namespace std;
double cal(double w,double h){
double r=h/(2*(pi+1));
if(r>w/2)
r=w/2;
double result1=pi*r*r*w;
r=w/(2*pi);
double result2=pi*r*r*(h-2*r);
cout<<fixed<<setprecision(3)<<max(result1,result2)<<endl;
}
int main(){
double w,h;
cin>>w>>h;
while(!(w==0&&h==0)){
cal(w,h);
cin>>w>>h;
}
return 0;;
}
}
巧解数学问题利用C++求解经典数学问题1.公倍数与公因数利用辗转相除法,我们可以很方便地求得两个数的最大公因数(greatest common divisor,gcd);将两个数相乘再除以最大公因数即可得到最小公倍数(least common multiple, lcm)。首先介绍一下辗转相除法:#include<iostream>
#include<cstdio>
using namesapce std;
int fun(int m,int n)
{
int rem;//余数,当余数为零的时候,最后的m即为最大公约数
//先用较小的数对较大的数取余,再用余数对较小的数取余,直到余数为零
while(n>0)
{
rem=m%n;
m=n;
n=rem;
}
return m;//将结果返回
}
int main(){
int n,m;
cin>>m>>n;
cout<<"m和n的最大公约数为:"<<fun(m,n)<<endl;
return 0;
}
//简化一下,用递归来求
int fun(int m,int n)
{
if(n==0) return m;
return (fun(n,m%n);
}
//再简化一下
int gcd(int m,int n){
return n ? gcd(n,m%n):m;
}
题解:int gcd(int a,int b)
{
return b==0 ? a:gcd(b,a%b);
}
int lcm(int a,int b)
{
return a*b/gcd(a,b);
}
进一步地,我们也可以通过扩展欧几里得算法(extended gcd)在求得 a 和 b 最大公因数的同时,也得到它们的系数 x 和 y,从而使 ax + by = gcd(a, b)。int xGCD(int a,int b,int &x,int &y)
{
if(!b){
x=1,y=0;
return 0;
}
int x1,y1,gcd=xGCD(b,a%b,x1,y1);
x=y1,y=x1-(a/b)*y1;
return gcd;
}
2.质数质数又称素数,指的是在大于1的自然数中,除了1和他本身以外不再有其他因数的自然数,值得注意的是,每一个数都可以分解成质数的乘积。埃拉托斯特尼筛法(Sieve of Eratosthenes,简称埃氏筛法)是非常常用的,判断一个整数是否是质数的方法。并且它可以在判断一个整数 n 时,同时判断所小于 n 的整数,因此非常适合这道题。其原理也十分易懂:从 1 到 n 遍历,假设当前遍历到 m,则把所有小于 n 的、且是 m 的倍数的整数标为和数;遍历完成后,没有被标为和数的数字即为质数。int countPrimes(int n)
{
if(n<=2) return 0;
vector<bool>prime(n,true);
int count=n-2;//去掉不是质数的1
for(int i=2;i<=n;++i)
{
if(prime[i]){
for(int j=2*i;j<n;j+=i)
{
if(prime[i]){
prime[j]=false;
--count;
}
}
}
}
return count;
}
利用质数的一些性质,我们可以进一步优化该算法int countPrimes(int n)
{
if(n<=2) return 0;
vector<bool>prime(n,true);
int i=3,sqrtn=sqrt(n),count=n/2;//偶数一定不是质数
while(i<=sqrtn)//最小质因子一定小于等于开方数
{
for(int j=i*i;j<n;j+=2*i)//避免偶数和重复遍历
{
if(prime[j])
{
--count;
prime[j]=false;
}
}
do{
i+=2;
}while(i<=sqrtn&&!prime[i]);//避免偶数和重复遍历
}
return count;
}
3.数字处理进制转换类型的题,通常是利用除法和取模(mod)来进行计算,同时也要注意一些细节,如负数和零。如果输出是数字类型而非字符串,则也需要考虑是否会超出整数上下界。string convertToBase7(int num)
{
if(num==0) return "0";
bool is_negative=num<0;
if(is_negative) num= -num;
string ans;
while(num)
{
int a=num/7,b=num%7;
ans=to_string(b)+ans;
num=a;
}
return is_negative ? "-" + ans: ans;
}
题目一:给定一个非负整数,判断它的阶乘结果的结尾有几个零。每个尾部的 0 由 2 × 5 = 10 而来,因此我们可以把阶乘的每一个元素拆成质数相乘,统计有多少个 2和 5。明显的,质因子 2 的数量远多于质因子 5 的数量,因此我们可以只统计阶乘结果里有多少个质因子5。int trailingZeros(int n)
{
return n==0 ? 0:n/5+trailingZeros(n/5);
}
题目二:给定两个由数字组成的字符串,求他们相加的结果因为相加运算是从后往前进行的,所以可以先翻转字符串,再逐位计算。这种类型的题考察的是细节,如进位、位数差等等。string addStrings(string num1,string num2)
{
string output("");
reverse(num1.begin(),num1.end());
reverse(num2.begin(),num2.end());
int onelen=num1.length(),twolen=num2.length();
if(onelen<=twolen)
{
swap(num1,num2);
swap(onelen,twolen);
}
int addbit;
for(int i=0;i<twolen;++i)
{
int cur_sum=(num1[i]-'0')+(num2[i]-'0')+addbit;
output+=tot_string((cur_sum)%10);
addbit=cur_sum<10?0:1;
}
for(int i=twolen;i<onelen;++i)
{
int cur_sum=(num1[i]-'0')+addbit;
output+=to_string((cur_sum)%10);
addbit=cur_sum<10?0:1;
}
if(addbit)
{
output+="1";
}
reverse(output.begin(),output.end());
return output;
}
题目三:判断一个数字是否是3的次方有两种方法,一种是利用对数。设 log3n = m,如果 n 是 3 的整数次方,那么 m 一定是整数。bool isPowerOfThree(int n){
return fmod(log10(n)/log10(3),1)==0;
}
另一种方法是,因为在 int 范围内 3 的最大次方是 319 = 1162261467,如果 n 是 3 的整数次方,那么 1162261467 除以 n 的余数一定是零;反之亦然。bool isPowerOfThree(int n)
{
return n>0&&1162261467%n==0;
}
4.随机与取样给定一个数组,要求实现两个指令函数。第一个函数“shuffle”可以随机打乱这个数组,第二个函数“reset”可以恢复原来的顺序。我们采用经典的 Fisher-Yates 洗牌算法,原理是通过随机交换位置来实现随机打乱,有正向和反向两种写法,且实现非常方便。注意这里“reset”函数以及类的构造函数的实现细节。class Solution{
vector<int>origin;
public:
Solution(vector<int>nums):origin(std::move(nums)){}
vector<int>reset(){
return origin;
}
vector<int>shuffled(){
if(origin.empty()) return {};
vector<int>shuffled(origin);
int n=origin.size();
//可以使用反向或者正向洗牌,效果相同
//反向洗牌:
for(int i=n-1;i>=0;--i)
{
swap(shuffles[i],shuffled[rand()%(i+1)]);
}
//正向洗牌
//for(int i=0;i<n;++i){
//
int pos=rand()%(n-i);
//
swap(shuffled[i],shuffled[i+pos]);
//}
return shuffled;
}
};
题目一:给定一个数组,数组每个位置表示该位置的权重,要求按照权重的概率去随机采样输入是一维正整数数组,表示权重;和一个包含指令字符串的一维数组,表示运行几次随机采样。输出是一维整数数组,表示随机采样的整数在数组中的位置。我们可以先使用 partial_sum 求前缀和(即到每个位置为止之前所有数字的和),这个结果对于正整数数组是单调递增的。每当需要采样时,我们可以先随机产生一个数字,然后使用二分法查找其在前缀和中的位置,以模拟加权采样的过程。这里的二分法可以用 lower_bound 实现。以样例为例,权重数组[1,3]的前缀和为[1,4]。如果我们随机生成的数字为1,那么 lower_bound返回的位置为 0;如果我们随机生成的数字是 2、3、4,那么 lower_bound 返回的位置为 1。class Solution{
vector<int>sums;
public:
Solution(vector<int>weights):sums(std::move(weights)){
partial_sum(sums.begin(),sums.end(),sums.begin());
}
int pickIndex(){
int pos=(rand()%sums.back())+1;
return lower_bound(sums.begin(),sums.end(),pos)-sums.begin();
}
};
题目二:给定一个单向链表,要求设计一个算法,可以随机取得其中的一个数字。不同于数组,在未遍历完链表前,我们无法知道链表的总长度。这里我们就可以使用水库采样:遍历一次链表,在遍历到第 m 个节点时,有 1m 的概率选择这个节点覆盖掉之前的节点选择。class Solution{
ListNode*head;
public:
Solution(ListNode*n):head(n){}
int getRandom(){
int ans=head->val;
ListNode*node=head-<next;
int i=2;
while(node){
if((rand()%i)==0){
ans=node->val;
}
++i;
node=node->next;
}
return ans;
}
}
}

我要回帖

更多关于 c语言计算题目及答案 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信