美国数学家维纳(N.Wiener)智力早熟,11岁就上了大学。他曾在1935~1936年应邀来中国清华大学讲学。一次,他参加某个重要会议,年轻的脸孔引人注目。因而有人询问他的年龄,他回答说:“我年龄的立方是个4位数。我年龄的4次方是个6位数。这10个数字正好包含了从0到9这10个数字,每一个都刚好出现1次。”ios
请你推算一下,他当时到底有多年轻。经过浏览器,直接提交他那时的年龄数字。注意:不要提交解答过程,或其它的说明文字。c++
代码:算法
#include<iostream> using namespace std; int main(){ for(int i=10;i<50;i++){ int _3=i*i*i; int _4=_3*i; if(_3>=1000&&_3<10000&&_4>=100000&&_4<1000000){ printf("%d %d %d\n",i,_3,_4); } } return 0; } //输出结果为: //18 5832 104976 //19 6859 130321 //20 8000 160000 //21 9261 194481
因为这是填空题,只要能算出结果便可,先把可能的结果输出,根据判断年龄为18的时候,0-9每一个数字只出现1次符合条件。编程
小明是个急性子,上小学的时候常常把老师写在黑板上的题目抄错了。数组
有一次,老师出的题目是:36 x 495 = ?浏览器
他却给抄成了:396 x 45 = ?函数
但结果却很戏剧性,他的答案居然是对的!!spa
由于 36 * 495 = 396 * 45 = 17820设计
相似这样的巧合状况可能还有不少,好比:27 * 594 = 297 * 54code
假设 a b c d e 表明1~9不一样的5个数字(注意是各不相同的数字,且不含0)
能知足形如: ab * cde = adb * ce 这样的算式一共有多少种呢?
请你利用计算机的优点寻找全部的可能,并回答不一样算式的种类数。
知足乘法交换律的算式计为不一样的种类,因此答案确定是个偶数。
答案直接经过浏览器提交。
注意:只提交一个表示最终统计种类数的数字,不要提交解答过程或其它多余的内容。
代码:
暴力枚举列出全部可能结果
#include<iostream> using namespace std; int main(){ int ans=0; for(int a=1;a<=9;a++){ for(int b=1;b<=9;b++){ if(b!=a){//各个数字不相同判断 for(int c=1;c<=9;c++){ if(c!=a&&c!=b){//各个数字不相同判断 for(int d=1;d<=9;d++){ if(d!=a&&d!=b&&d!=c){//各个数字不相同判断 for(int e=1;e<=9;e++){ if(e!=a&&e!=b&&e!=c&&e!=d){//各个数字不相同判断 if((a*10+b)*(c*100+d*10+e)==(a*100+d*10+b)*(c*10+e)){ ans++; } } } } } } } } } } cout<<ans<<endl; return 0; } //输出结果:142
暴力到没朋友
填空题应第一考虑可否暴力枚举,简单粗暴。
小明参加了学校的趣味运动会,其中的一个项目是:跳格子。
地上画着一些格子,每一个格子里写一个字,以下所示:
比赛时,先站在左上角的写着“从”字的格子里,能够横向或纵向跳到相邻的格子里,但不能跳到对角的格子或其它位置。一直要跳到“华”字结束。
要求跳过的路线恰好构成“从我作起振兴中华”这句话。
请你帮助小明算一算他一共有多少种可能的跳跃路线呢?
答案是一个整数,请经过浏览器直接提交该数字。
注意:不要提交解答过程,或其它辅助说明类的内容。
代码:
简单理解就是从“从”到“华”有多少条路能够走
#include<iostream> using namespace std; bool vis[5][5]; int f(int x,int y){ if(x==3&&y==4) //已经到"华"只有一种 return 1; else if(x==3) //已经到最后一行,只能往右走 return f(x,y+1); else if(y==4) //已经到最后一列,只能往下走 return f(x+1,y); else return f(x+1,y)+f(x,y+1); } int main(){ cout<<f(0,0); return 0; } //输出结果:35
递归的方法:找重复、找状态、找出口
幻方是把一些数字填在方格中,使得行、列、两条对角线的数字之和都相等。
欧洲最著名的幻方是德国数学家、画家迪勒创做的版画《忧郁》中给出的一个4阶幻方。
他把1,2,3,...16 这16个数字填写在4 x 4的方格中。
如图所示,即:
表中有些数字已经显露出来,还有些用?和*代替。
请你计算出? 和 * 所表明的数字。并把 * 所表明的数字做为本题答案提交。
答案是一个整数,请经过浏览器直接提交该数字。
注意:不要提交解答过程,或其它辅助说明类的内容。
代码:
已经使用的数字:1,9,11,13,16
未使用的数字:2,3,4,5,6,7,8,10,12,14,15
由于每一个空只能填一个数字,每一个数字只能填一次,故使用暴力法,求未使用的数字进行全排列,即它们可能组成的各类顺序,依次填入方格中进行判断,当知足条件时返回便可。
在c++中有相应的全排列公式next_permutation(),其它语言须要手动实现。
#include<iostream> #include<vector> #include<algorithm> using namespace std; int a[]={2,3,4,5,6,7,8,10,12,14}; void check(vector<int> arr){ int r1=16+arr[0]+arr[1]+13; int r2=arr[2]+arr[3]+11+arr[4]; int r3=9+arr[5]+arr[6]+arr[7]; int r4=arr[8]+15+arr[9]+1; int c1=16+arr[2]+9+arr[8]; int c2=arr[0]+arr[3]+arr[5]+15; int c3=arr[1]+11+arr[6]+arr[9]; int c4=13+arr[4]+arr[7]+1; int l=16+arr[3]+arr[6]+1; int r=13+11+arr[5]+arr[8]; if(r1==r2&&r2==r3&&r3==r4&&r4==c1&&c1==c2&&c2==c3&&c3==c4&&c4==l&&l==r){ cout<<arr[7]<<endl; } } int main(){ vector<int> arr; for(int i=0;i<10;i++){ arr.push_back(a[i]); } do{ check(arr); }while(next_permutation(arr.begin(),arr.end())); return 0; }
咱们常常会用到求两个整数的最大公约数和最小公倍数的功能。
下面的程序给出了一种算法。
函数 myfunc 接受两个正整数a,b
通过运算后打印出 它们的最大公约数和最小公倍数。
此时,调用 myfunc(15,20)
将会输出:
5
60
请分析代码逻辑,并推测划线处的代码,经过网页提交。
注意:仅把缺乏的代码做为答案,千万不要填写多余的代码、符号或说明文字!!
// 交换数值 void swap(int *a,int *b) { int temp; temp=*a; *a=*b; *b=temp; } void myfunc(int a, int b) //使用展转相除法求最大公约数 { int m,n,r; if(a<b) swap(&a,&b); m=a;n=b;r=a%b; while(r!=0) { a=b;b=r; r=a%b; } printf("%d\n",b); // 最大公约数 printf("%d\n", ____________________________________); // 最小公倍数 } //已知最大公约数b时可使用公式 n*m/b a,b已经改变,n,m是a,b的拷贝故使用n,m. //答案:n*m/b
通常的排序有许多经典算法,如快速排序、希尔排序等。
但实际应用时,常常会或多或少有一些特殊的要求。咱们不必套用那些经典算法,能够根据实际状况创建更好的解法。
好比,对一个整型数组中的数字进行分类排序:
使得负数都靠左端,正数都靠右端,0在中部。注意问题的特色是:负数区域和正数区域内并不要求有序。能够利用这个特色经过1次线性扫描就结束战斗!!
如下的程序实现了该目标。
其中x指向待排序的整型数组,len是数组的长度。
若是给定数组:
25,18,-2,0,16,-5,33,21,0,19,-16,25,-3,0
则排序后为:
-3,-2,-16,-5,0,0,0,21,19,33,25,16,18,25
请分析代码逻辑,并推测划线处的代码,经过网页提交
注意:仅把缺乏的代码做为答案,千万不要填写多余的代码、符号或说明文字!!
void sort3p(int* x, int len) { int p = 0; int left = 0; int right = len-1; while(p<=right){ if(x[p]<0){ int t = x[left]; x[left] = x[p]; x[p] = t; left++; p++; }else if(x[p]>0){ int t = x[right]; x[right] = x[p]; x[p] = t; right--; } else{ p++; //填空位置 } } }
p 指向当前要判断元素的下边
left 指向元素的左边都小于0,right指向元素的右边都大于0。
问题描述
小张是软件项目经理,他带领3个开发组。工期紧,今天都在加班呢。为鼓舞士气,小张打算给每一个组发一袋核桃(据传言能补脑)。他的要求是:
输入格式
输入包含三个正整数a, b, c,表示每一个组正在加班的人数,用空格分开(a,b,c<30)
输出格式
输出一个正整数,表示每袋核桃的数量。
样例输入1
2 4 5
样例输出1
20
样例输入2
3 1 1
样例输出2
3
代码:
简单理解就是要求这三个数的最小公倍数,使用暴力枚举,最坏三者的最小公倍数为a * b * c。
#include<iostream> using namespace std; int main(){ int a,b,c; cin>>a>>b>>c; for(int i=1;i<=a*b*c;i++){ if(i%a==0&&i%b==0&&i%c==0){ cout<<i<<endl; break; } } return 0; }
小明为某机构设计了一个十字型的徽标(并不是红十字会啊),以下所示:
..$$$$$$$$$$$$$.. ..$...........$.. $$$.$$$$$$$$$.$$$ $...$.......$...$ $.$$$.$$$$$.$$$.$ $.$...$...$...$.$ $.$.$$$.$.$$$.$.$ $.$.$...$...$.$.$ $.$.$.$$$$$.$.$.$ $.$.$...$...$.$.$ $.$.$$$.$.$$$.$.$ $.$...$...$...$.$ $.$$$.$$$$$.$$$.$ $...$.......$...$ $$$.$$$$$$$$$.$$$ ..$...........$.. ..$$$$$$$$$$$$$..
对方同时也须要在电脑dos窗口中以字符的形式输出该标志,并能任意控制层数。
输入1 ,则输出
..$$$$$.. ..$...$.. $$$.$.$$$ $...$...$ $.$$$$$.$ $...$...$ $$$.$.$$$ ..$...$.. ..$$$$$..
输入
一个正整数 n (n< 30) 表示要求打印图形的层数。
输出
对应包围层数的该标志。
样例输入
3
样例输出
..$$$$$$$$$$$$$.. ..$...........$.. $$$.$$$$$$$$$.$$$ $...$.......$...$ $.$$$.$$$$$.$$$.$ $.$...$...$...$.$ $.$.$$$.$.$$$.$.$ $.$.$...$...$.$.$ $.$.$.$$$$$.$.$.$ $.$.$...$...$.$.$ $.$.$$$.$.$$$.$.$ $.$...$...$...$.$ $.$$$.$$$$$.$$$.$ $...$.......$...$ $$$.$$$$$$$$$.$$$ ..$...........$.. ..$$$$$$$$$$$$$..
代码:
假设最外层为第一层
n=3时
为17 * 17的方格;第一行$个数13
n=2时
为13 * 13的方格; 第一行$个数9
n=1时
为 9 * 9的方格; 第一行$个数5
L表示左侧边界为0,R表示右侧边界为9+4*(n-1)-1 (下标从0开始R的下标须要减1)
写死后,只输出最外一层
#include<iostream> using namespace std; char arr[9+4*28][9+4*28]; int N; //一共有几层 int L=0; //最外层左边界下标 int R; //最外层右边界下标 void printAll(int left,int right){ for(int i=left;i<=right;i++){ for(int j=left;j<=right;j++){ if(arr[i][j]!='$') arr[i][j]='.'; cout<<arr[i][j]; } cout<<endl; } } int main(){ cin>>N; cout<<N<<endl; R=9+4*(N-1)-1; //求出最外层右边界下标 //处理第一行和最后一行 for(int i=2;i<=R-2;i++){ arr[0][i]='$'; arr[R][i]='$'; } //处理第二行和倒数第二行 arr[1][2]='$'; arr[1][R-2]='$'; arr[R-1][2]='$'; arr[R-1][R-2]='$'; //处理第三行和倒数第三行 arr[2][0]='$'; arr[2][1]='$'; arr[2][2]='$'; arr[2][R]='$'; arr[2][R-1]='$'; arr[2][R-2]='$'; arr[R-2][0]='$'; arr[R-2][1]='$'; arr[R-2][2]='$'; arr[R-2][R]='$'; arr[R-2][R-1]='$'; arr[R-2][R-2]='$'; //处理两边 for(int i=3;i<=R-3;i++){ arr[i][0]='$'; arr[i][R]='$'; } printAll(L,R); return 0; } 输入: 3 输出: ..$$$$$$$$$$$$$.. ..$...........$.. $$$...........$$$ $...............$ $...............$ $...............$ $...............$ $...............$ $...............$ $...............$ $...............$ $...............$ $...............$ $...............$ $$$...........$$$ ..$...........$.. ..$$$$$$$$$$$$$.. 输入: 1 输出: ..$$$$$.. ..$...$.. $$$...$$$ $.......$ $.......$ $.......$ $$$...$$$ ..$...$.. ..$$$$$..
而后找规律,发现每层只是左右边界不一样L每次加2,R每次减2,故单独写一个方法输出第n层的图像
#include<iostream> using namespace std; char arr[9+4*28][9+4*28]; int N; //一共有几层 int L=0; //最外层左边界下标 int R; //最外层右边界下标 void printAll(int left,int right){ for(int i=left;i<=right;i++){ for(int j=left;j<=right;j++){ if(arr[i][j]!='$') arr[i][j]='.'; cout<<arr[i][j]; } cout<<endl; } } void dealN(int n){ int l,r; //当前层的左右边界,由于时方格,l也表示上边界,r也表示下边界 l=2*(N-n); r=R-2*(N-n); //处理第一行和最后一行 for(int i=l+2;i<=r-2;i++){ arr[l][i]='$'; arr[r][i]='$'; } //处理第二行和倒数第二行 arr[l+1][l+2]='$'; arr[l+1][r-2]='$'; arr[r-1][l+2]='$'; arr[r-1][r-2]='$'; //处理第三行和倒数第三行 arr[l+2][l]='$'; arr[l+2][l+1]='$'; arr[l+2][l+2]='$'; arr[l+2][r]='$'; arr[l+2][r-1]='$'; arr[l+2][r-2]='$'; arr[r-2][l]='$'; arr[r-2][l+1]='$'; arr[r-2][l+2]='$'; arr[r-2][r]='$'; arr[r-2][r-1]='$'; arr[r-2][r-2]='$'; //处理两边 for(int i=l+3;i<=r-3;i++){ arr[i][l]='$'; arr[i][r]='$'; } } int main(){ cin>>N; R=9+4*(N-1)-1; //求出最外层右边界下标 for(int i=N;i>0;i--){ dealN(i); } //最后处理中间十字 for(int i=2*N;i<2*N+5;i++){ arr[2*N+2][i]='$'; arr[i][2*N+2]='$'; } printAll(L,R); return 0; } 输入3时 ..$$$$$$$$$$$$$.. ..$...........$.. $$$.$$$$$$$$$.$$$ $...$.......$...$ $.$$$.$$$$$.$$$.$ $.$...$...$...$.$ $.$.$$$.$.$$$.$.$ $.$.$...$...$.$.$ $.$.$.$$$$$.$.$.$ $.$.$...$...$.$.$ $.$.$$$.$.$$$.$.$ $.$...$...$...$.$ $.$$$.$$$$$.$$$.$ $...$.......$...$ $$$.$$$$$$$$$.$$$ ..$...........$.. ..$$$$$$$$$$$$$..
问题描述
100 能够表示为带分数的形式:100 = 3 + 69258 / 714。
还能够表示为:100 = 82 + 3546 / 197。
注意特征:带分数中,数字1~9分别出现且只出现一次(不包含0)。
相似这样的带分数,100 有 11 种表示法。
输入格式
从标准输入读入一个正整数N (N<1000*1000)
输出格式
程序输出该数字用数码1~9不重复不遗漏地组成带分数表示的所有种数。
注意:不要求输出每一个表示,只统计有多少表示法!
样例输入1
100
样例输出1
11
样例输入2
105
样例输出2
6
分析:
生成1-9这9个数字的全排列,先在可能的位置插入“+”号,而后在可能的位置插入“/”号,再验证等式。
#include<iostream> #include<algorithm> #include<string> using namespace std; int main(){ int n,ans=0; cin>>n; string s="123456789"; do{ for(int i=1;i<=7;i++){ // i:"+"前串的长度 string a=s.substr(0,i); int inta=atoi(a.c_str()); // string 转换 int if(inta>=n) break; for(int j=1;j<=9-i-1;j++){ // j: "+"和"/"之间串的长度 string b=s.substr(i,j); string c=s.substr(i+j);// "/"后面的串 int intb=atoi(b.c_str()); int intc=atoi(c.c_str()); if(intb%intc==0&&inta+intb/intc==n) ans++; } } }while(next_permutation(s.begin(),s.end())); cout<<ans<<endl; return 0; }
结果时正确的,可是运行超时,反复使用substr()
函数会消耗大量时间,须要对代码进行改进。
#include<iostream> #include<algorithm> #include<string> using namespace std; //本身实现一个函数,经过从pos截取len长度的字符串 int parse(const char *arr,int pos,int len){ int ans=0; int t=1; for(int i=pos+len-1;i>=pos;i--){ ans+=(arr[i]-'0')*t; t*=10; } return ans; } int main(){ int n,ans=0; cin>>n; string s="123456789"; do{ const char *str=s.c_str(); for(int i=1;i<=7;i++){ // i:"+"前串的长度 // string a=s.substr(0,i); // int inta=atoi(a.c_str()); // string 转换 int int inta=parse(str,0,i); if(inta>=n) break; for(int j=1;j<=9-i-1;j++){ // j: "+"和"/"之间串的长度 // string b=s.substr(i,j); // string c=s.substr(i+j);// "/"后面的串 // int intb=atoi(b.c_str()); // int intc=atoi(c.c_str()); int intb=parse(str,i,j); int intc=parse(str,i+j,9-i-j); if(intb%intc==0&&inta+intb/intc==n) ans++; } } }while(next_permutation(s.begin(),s.end())); cout<<ans<<endl; return 0; } //完美,测评经过。
以下图所示,3 x 3 的格子中填写了一些整数。
+--*--+--+ |10* 1|52| +--****--+ |20|30* 1| *******--+ | 1| 2| 3| +--+--+--+
咱们沿着图中的星号线剪开,获得两个部分,每一个部分的数字和都是60。
本题的要求就是请你编程断定:对给定的m x n 的格子中的整数,是否能够分割为两个部分,使得这两个区域的数字和相等。
若是存在多种解答,请输出包含左上角格子的那个区域包含的格子的最小数目。
若是没法分割,则输出 0。
输入格式
程序先读入两个整数 m n 用空格分割 (m,n<10)。
表示表格的宽度和高度。
接下来是n行,每行m个正整数,用空格分开。每一个整数不大于10000。
输出格式
输出一个整数,表示在全部解中,包含左上角的分割区可能包含的最小的格子数目。
样例输入1
3 3
10 1 52
20 30 1
1 2 3
样例输出1
3
样例输入2
4 3
1 1 1 1
1 30 80 2
1 1 1 100
样例输出2
10
#include<iostream> #include<algorithm> using namespace std; int m,n,total; int g[10][10],ans=100; bool vis[10][10]; int dx[]={1, 0,-1,0}; int dy[]={0,-1, 0,1}; bool in(int x,int y){ //判断该位置是否合法 if(x>=0&&x<=n-1&&y>=0&&y<=m-1){ return true; }else{ return false; } } void f(int x,int y,int sum,int cnt){ // printf("(%d,%d)sum=%d,cnt=%d\n",x,y,sum,cnt); if(sum>total/2) return; if(sum==total/2){ ans=min(ans,cnt); return; } vis[x][y]=true; for(int i=0;i<4;i++){ int tx=x+dx[i]; int ty=y+dy[i]; if(in(tx,ty)&&!vis[tx][ty]){ f(tx,ty,sum+g[x][y],cnt+1); } } vis[x][y]=false; } int main(){ cin>>m>>n; for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ cin>>g[i][j]; total+=g[i][j]; //求出全部元素的和 } } f(0,0,0,0); cout<<ans<<endl; return 0; }
上面的代码能够经过蓝桥杯练习系统,但在有些特殊的状况会执行错误,例如:
1 1
1 2
应输出3,运行结果是0,表示没法分割。