1.哥德巴赫分解
哥德巴赫猜想认为:不小于4的偶数都可以表示为两个素数的和。
你不需要去证明这个定理,但可以通过计算机对有限数量的偶数进行分解,验证是否可行。
实际上,一般一个偶数会有多种不同的分解方案,我们关心包含较小素数的那个方案。
对于给定数值范围,我们想知道这些包含较小素数方案中最大的素数是多少。
比如,100以内,这个数是19,它由98的分解贡献。
你需要求的是10000以内,这个数是多少?
注意,需要提交的是一个整数,不要填写任何多余的内容(比如,说明性的文字)
答案:173
include<bits/stdc++.h>
using namespace std;
bool isprime(int x)
{
for(int i=2;i<=sqrt(x);i++)
if(x%i==0)
return false;
return true;
}
int main()
{
int ans=1,n;
cin>>n;
for(int i=n;i>=4;i-=2)
{
for(int j=2;j<=i;j++)
{
if(isprime(j) && isprime(i-j))
{
ans=max(ans,j);break;
}
}
}
cout<<ans<<endl;
return 0;
}
2.数字划分
w星球的长老交给小明一个任务:
1,2,3…16 这16个数字分为两组。
要求:
这两组数字的和相同,
并且,两组数字的平方和也相同,
并且,两组数字的立方和也相同。
请你利用计算机的强大搜索能力解决这个问题。
并提交1所在的那个分组的所有数字。
这些数字要从小到大排列,两个数字间用一个空格分开。
即类似:1 4 5 8 … 这样的答案。
注意,只提交这一组数字,不要填写任何多余的内容。
笨笨有话说:
只要一个组的成员确定了,另一个组的成员也就确定了。枚举一个组的成员就可以了。
凭直觉,两个组的成员数目不会差太多吧。
歪歪有话说:
既然求 1 所在的那个组,那只要枚举剩余的成员就可以了。
貌似都是8个成员的可能性很大啊。
答案:1 4 6 7 10 11 13 16
思路:暴力搜索就行,题目最后给的提示很有用
#include<bits/stdc++.h>
using namespace std;
int vis[20];
int a[20];
int sum1,sum2,sum3,flag;
void dfs(int num,int sum,int sqrt,int lifang)
{
if(sum>sum1/2 || sqrt>sum2/2 || lifang>sum3/2 || flag)
return;
//cout<<num<<" "<<sum<<" "<<sqrt<<" "<<lifang<<endl;
//cout<<"in"<<endl;
if(sum==sum1/2 && sqrt==sum2/2 && lifang==sum3/2)
{
flag=1;
for(int i=0;i<num;i++)
cout<<a[i]<<" ";
return;
}
for(int i=1;i<=16;i++)
{
if(!vis[i])
{
a[num]=i;
vis[i]=1;
dfs(num+1,sum+i,sqrt+i*i,lifang+i*i*i);
vis[i]=0;
}
}
}
int main()
{
vis[1]=1;
a[0]=1;
for(int i=1;i<=16;i++)
{
sum1+=i;
sum2+=i*i;
sum3+=i*i*i;
}
cout<<sum1<<" "<<sum2<<" "<<sum3<<endl;
dfs(1,1,1,1);
return 0;
}
3.数位和
数学家高斯很小的时候就天分过人。一次老师指定的算数题目是:1+2+…+100。
高斯立即做出答案:5050!
这次你的任务是类似的。但并非是把一个个的数字加起来,而是对该数字的每一个数位作累加。
这样从1加到100的“和”是:901
从10加到15是:21,也就是:1+0+1+1+1+2+1+3+1+4+1+5,这个口算都可以出结果的。
按这样的“加法”,从1加到1000是多少呢? 请通过浏览器提交该结果。
当然,我们并不期望你能像高斯一样,发现数字背后深奥的秘密,只要请计算机帮忙,一切都easy!
注意:你需要提交的是一个整数,不要填写任何多余的内容(比如:说明性文字)
答案:13501
#include<bits/stdc++.h>
using namespace std;
int f(int x)
{
int sum=0;
while(x)
{
sum+=x%10;
x/=10;
}
return sum;
}
int main()
{
int n,ans=0;
cin>>n;
for(int i=1;i<=n;i++)
{
ans+=f(i);
}
cout<<ans<<endl;
return 0;
}
4.36进制
对于16进制,我们使用字母A-F来表示10及以上的数字。
如法炮制,一直用到字母Z,就可以表示36进制。
36进制中,A表示10,Z表示35,AA表示370
你能算出 MANY 表示的数字用10进制表示是多少吗?
请提交一个整数,不要填写任何多余的内容(比如,说明文字)
答案:1040254
思路:像十进制一样做就好了
#include<bits/stdc++.h>
using namespace std;
int main()
{
string s;
cin>>s;
int len=s.size();
int ans=0;
for(int i=0;i<len;i++)
{
int x=s[i]-'A'+10;
cout<<x<<endl;
ans*=36;
ans+=x;
}
cout<<ans<<endl;
return 0;
}
5.平方十位数
由0~9这10个数字不重复、不遗漏,可以组成很多10位数字。
这其中也有很多恰好是平方数(是某个数的平方)。
比如:1026753849,就是其中最小的一个平方数。
请你找出其中最大的一个平方数是多少?
注意:你需要提交的是一个10位数字,不要填写任何多余内容。
思路:全排列+暴力就好
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int a[15]={0,1,2,3,4,5,6,7,8,9};
int main()
{
ll ans=0;
do
{
if(!a[0])
continue;
ll x=a[0];
for(int i=1;i<=9;i++)
x=x*10+a[i];
if((ll)sqrt(x)*sqrt(x)==x)
{
ans=max(ans,x);
//cout<<x<<endl;
}
}while(next_permutation(a,a+10));
cout<<ans<<endl;
return 0;
}
6.生命游戏
康威生命游戏是英国数学家约翰·何顿·康威在1970年发明的细胞自动机。
这个游戏在一个无限大的2D网格上进行。
初始时,每个小方格中居住着一个活着或死了的细胞。
下一时刻每个细胞的状态都由它周围八个格子的细胞状态决定。
具体来说:
- 当前细胞为存活状态时,当周围低于2个(不包含2个)存活细胞时, 该细胞变成死亡状态。(模拟生命数量稀少)
- 当前细胞为存活状态时,当周围有2个或3个存活细胞时, 该细胞保持原样。
- 当前细胞为存活状态时,当周围有3个以上的存活细胞时,该细胞变成死亡状态。(模拟生命数量过多)
- 当前细胞为死亡状态时,当周围有3个存活细胞时,该细胞变成存活状态。 (模拟繁殖)
当前代所有细胞同时被以上规则处理后, 可以得到下一代细胞图。按规则继续处理这一代的细胞图,可以得到再下一代的细胞图,周而复始。
例如假设初始是:(X代表活细胞,.代表死细胞)
…
…
.XXX.
…
下一代会变为:
…
…X…
…X…
…X…
…
康威生命游戏中会出现一些有趣的模式。例如稳定不变的模式:
…
.XX.
.XX.
…
还有会循环的模式:
… … …
.XX… .XX… .XX…
.XX… .X… .XX…
…XX. -> …X. -> …XX.
…XX. …XX. …XX.
… … …
本题中我们要讨论的是一个非常特殊的模式,被称作"Gosper glider gun":
…
…X…
…X.X…
…XX…XX…XX.
…X…X…XX…XX.
.XX…X…X…XX…
.XX…X…X.XX…X.X…
…X…X…X…
…X…X…
…XX…
…
答案:166666713
这个博客讲的挺详细的,自己的代码还是有点问题。。https://www.cnblogs.com/chiweiming/p/10693184.html
7.图书排列
将编号为1~10的10本书排放在书架上,要求编号相邻的书不能放在相邻的位置。
请计算一共有多少种不同的排列方案。
注意,需要提交的是一个整数,不要填写任何多余的内容。
答案:479306
思路:全排列+暴力
#include<bits/stdc++.h>
using namespace std;
int a[15]={1,2,3,4,5,6,7,8,9,10};
int main()
{
int ans=0;
do
{
int flag=0;
for(int i=1;i<9;i++)
if(abs(a[i]-a[i-1])==1 || abs(a[i]-a[i+1])==1)
{
flag=1;break;
}
if(!flag)
ans++;
}while(next_permutation(a,a+10));
cout<<ans<<endl;
return 0;
}
8.磁砖样式
小明家的一面装饰墙原来是 3*10 的小方格。
现在手头有一批刚好能盖住2个小方格的长方形瓷砖。
瓷砖只有两种颜色:黄色和橙色。
小明想知道,对于这么简陋的原料,可以贴出多少种不同的花样来。
小明有个小小的强迫症:忍受不了任何22的小格子是同一种颜色。
(瓷砖不能切割,不能重叠,也不能只铺一部分。另外,只考虑组合图案,请忽略瓷砖的拼缝)
显然,对于 23 个小格子来说,口算都可以知道:一共10种贴法,如【p1.png所示】
但对于 3*10 的格子呢?肯定是个不小的数目,请你利用计算机的威力算出该数字。
注意:你需要提交的是一个整数,不要填写任何多余的内容(比如:说明性文字)
答案:101466
思路:dfs,记得去重
#include<bits/stdc++.h>
using namespace std;
int n,m,ans;
int a[105][105];
map<string,int> mp;
int check() //检查是否存在相同颜色的边长为4的小正方形
{
for(int i=0;i<n-1;i++)
for(int j=0;j<m-1;j++)
{
if(a[i][j]==a[i][j+1] && a[i][j]==a[i+1][j] && a[i][j]==a[i+1][j+1] )
return 0;
}
return 1;
}
int judge() //用map去重
{
string s;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
s+=a[i][j]+'0';
}
if(mp[s])
return 0;
mp[s]=1;
return 1;
}
void dfs(int num)
{
if(num>=n*m)
{
if(check() && judge())
ans++;
return;
}
int x,y,flag=1;
for(int i=0;i<n && flag;i++)
for(int j=0 ;j<m && flag;j++)
if(!a[i][j])
{
x=i;y=j;flag=0;
}
if(y+1<m && !a[x][y+1])
{
a[x][y]=a[x][y+1]=1;
dfs(num+2);
a[x][y]=a[x][y+1]=2;
dfs(num+2);
a[x][y]=a[x][y+1]=0;
}
if(x+1<n && !a[x+1][y])
{
a[x][y]=a[x+1][y]=1;
dfs(num+2);
a[x][y]=a[x+1][y]=2;
dfs(num+2);
a[x][y]=a[x+1][y]=0;
}
}
int main()
{
cin>>n>>m;
dfs(0);
cout<<ans<<endl;
return 0;
}
9.表达式计算
虽然我们学了许久的程序设计,但对于简单的四则混合运算式,如果让我们完全白手起家地编程来解析,还是有点棘手。
这里,我们简化一下问题,假设只有加法和乘法,并且没有括号来改变优先级。
再假设参加运算的都是正整数。
在这么多的限制条件下,表达式的解析似乎简单了许多。
下面的代码解决了这个问题。请仔细阅读源码,并填写划线部分缺少的代码。
#include <stdio.h>
int f3(const char* s, int begin, int end)
{
int sum = 0;
int i;
for(i=begin; i<end; i++){
if(s[i]==’ ') continue;
sum = sum * 10 + (s[i]-‘0’);
}
return sum;
}
int f2(const char* s, int begin, int end)
{
int p = begin;
int pro = 1;
while(1){
int p0 = p;
while(p!=end && s[p]!=’*’) p++;
pro *= _______________________________; //填空
if(p==end) break;
p++;
}
printf(“f2: pro=%d\n”, pro);
return pro;
}
int f(const char* s)
{
int p = 0;
int sum = 0;
while(1){
int p0 = p;
while(s[p]!=0 && s[p]!=’+’) p++;
sum += f2(s,p0,p);
if(s[p]==0) break;
p++;
}
return sum;
}
int main()
{
int x = f(“12+18+543+10”);
printf("%d\n", x);
return 0;
}
注意:只填写划线处缺少的内容,不要填写已有的代码或符号,也不要填写任何解释说明文字等。
答案:f3(s,p0,p)
10.希尔伯特曲线
希尔伯特曲线是以下一系列分形曲线 Hn 的极限。我们可以把 Hn 看作一条覆盖 2^n × 2^n 方格矩阵的曲线,曲线上一共有 2^n × 2^n 个顶点(包括左下角起点和右下角终点),恰好覆盖每个方格一次。
[p1.png]
Hn(n > 1)可以通过如下方法构造:
- 将 Hn-1 顺时针旋转90度放在左下角
- 将 Hn-1 逆时针旋转90度放在右下角
- 将2个 Hn-1 分别放在左上角和右上角
- 用3条单位线段把4部分连接起来
对于 Hn 上每一个顶点 p ,我们定义 p 的坐标是它覆盖的小方格在矩阵中的坐标(左下角是(1, 1),右上角是(2^n, 2^n),从左到右是X轴正方向,从下到上是Y轴正方向),
定义 p 的序号是它在曲线上从起点开始数第几个顶点(从1开始计数)。
以下程序对于给定的n(n <= 30)和p点坐标(x, y),输出p点的序号。请仔细阅读分析源码,填写划线部分缺失的内容。
#include <stdio.h>
long long f(int n, int x, int y) {
if (n == 0) return 1;
int m = 1 << (n - 1);
if (x <= m && y <= m) {
return f(n - 1, y, x);
}
if (x > m && y <= m) {
return 3LL * m * m + f(n - 1, ________________ , m * 2 - x + 1); // 填空
}
if (x <= m && y > m) {
return 1LL * m * m + f(n - 1, x, y - m);
}
if (x > m && y > m) {
return 2LL * m * m + f(n - 1, x - m, y - m);
}
}
int main() {
int n, x, y;
scanf("%d %d %d", &n, &x, &y);
printf("%lld", f(n, x, y));
return 0;
}
注意:只填写划线处缺少的内容,不要填写已有的代码或符号,也不要填写任何解释说明文字等。
答案:m+1-y
思路:找规律,m是现在的图的边长的一半,找旋转后小图中的的x,y与上一张图的x,y的关系