第三题 火柴棒等式[2,1]
这里介绍最简单的 便于理解的方法:
Sol 1 暴力枚举
因为n最大24 我们计算所有的四位数需要的火柴棒数量预处理
计算的时候 每一位需要的火柴棒数量可以int cnt[]={6,2,5,5,4,5,6,3,7,6};
最后计算的时候,枚举A 和 B
如果 数字A B A+B 的火柴棒数量=n-4 就是一个解(因为加号和等号都是两根)
Sol 2 打表
int f[25]={0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,8,9,6,9,29,39…………};
24根列完就OK了!
第四题 回文质数 Prime Palindromes[2,1]
写一个程序来找出范围[a,b] (5≤a
提示已经给了,先列举回文数,再判断是否为质数
这里有个神奇的小东西:
除了11,所有的偶数位数的回文数都是非质数,都被11整除
那我们枚举其他奇数位的回文数,再判断是否是质数就可以了!
列举长度为7的回文数:
for (int d1 = 1; d1 <= 9; d1+=2){ //偶数一定不是质数,最低(高)位一定是偶数
for (int d2 = 0; d2 <= 9; d2++){
for (int d3 = 0; d3 <= 9; d3++){
for(int d4=0;d4<=9;d4++){
pal = 1000000*d1 + 100000*d2 +10000*d3 + 1000*d4 +100*d3+ 10*d2 + d1;
if(pal<a || pal>b)continue; //判断要在范围内
if(ck(pal))printf("%lld\n",pal); //判断质数
}
}
}
}
第一题 陶陶摘苹果(升级版)[2,2]
又是一年秋季时,陶陶家的苹果树结了 n 个果子。陶陶又跑去摘苹果,这次他有一个 a 公分的椅子。当他手够不着时,他会站到椅子上再试试。
这次与 NOIp2005 普及组第一题不同的是:陶陶之前搬凳子,力气只剩下 s 了。当然,每次摘苹果时都要用一定的力气。陶陶想知道在s<0 之前最多能摘到多少个苹果。
现在已知 n 个苹果到达地上的高度 xi ,椅子的高度 a,陶陶手伸直的最大长度 b,陶陶所剩的力气s,陶陶摘一个苹果需要的力气 yi,求陶陶最多能摘到多少个苹果。
既然只输出最多摘多少个苹果,那我们就贪心,每次摘需要花费力气最小的苹果,如果摘不到就下一个力气次小的,依次类推
每个苹果有高度和力气两个参数,我们使用简便的pair
cmp()函数比较每个苹果的力气值,然后顺序摘取
第二题 三连击(升级版)[1,1]
之前的三连击题目一样,只不过比例改成了自定义输入,同之前的代码
解题报告一,三连击在里面
第三题 哥德巴赫猜想(升级版)[2,2]
1742年6月7日哥德巴赫写信给当时的大数学家欧拉,正式提出了以下的猜想:任何一个大于9的奇数都可以表示成3个质数之和。质数是指除了1和本身之外没有其他约数的数,如2和11都是质数,而6不是质数,因为6除了约数1和6之外还有约数2和3。需要特别说明的是1不是质数。
因为范围 9
复杂度O(NlogN)
int shai(void){
int p=-1;
for(int i=2;i<MAX;++i){
if(num[i])continue; //记录i有没有被筛走
pri[++p]=i; //下一个质数是i
for(int j=i*2;j<MAX;j+=i) //k倍都筛掉
num[j]=1; //j筛走了
}
return p;
}
然后枚举 质数 a b ,是否 n-a-b 也是质数即可
第四题 烤鸡[3,3]
猪猪 Hanke 特别喜欢吃烤鸡(本是同畜牲,相煎何太急!)Hanke 吃鸡很特别,为什么特别呢?因为他有 10种配料(芥末、孜然等),每种配料可以放 1 到 3 克,任意烤鸡的美味程度为所有配料质量之和。
现在, Hanke 想要知道,如果给你一个美味程度 n ,请输出这 10 种配料的所有搭配方案。
输入
11
输出
10
1 1 1 1 1 1 1 1 1 2
1 1 1 1 1 1 1 1 2 1
1 1 1 1 1 1 1 2 1 1
1 1 1 1 1 1 2 1 1 1
1 1 1 1 1 2 1 1 1 1
1 1 1 1 2 1 1 1 1 1
1 1 1 2 1 1 1 1 1 1
1 1 2 1 1 1 1 1 1 1
1 2 1 1 1 1 1 1 1 1
2 1 1 1 1 1 1 1 1 1
有一定难度的递归题目,答案还要求字典序升序输出
首先我采用了状态压缩做法(每种调料使用1/2/3 三种状态)3^10 也没超时间
试试就逝世
一通狂做,一看输出傻眼了:(最后答案反转了一下输出的)
这咋就这么奇怪呢?状态压缩是二进制方法实现的,二进制不保证字典序!
那就利用递归好好做吧
void pd(int pos,int now)
表示当前位置为pos ,用了调料now了
边界1 : 如果pos=10 表示处理完了 如果now!=n 表示用的不对,反之输出
边界2 优化: 如果当前位置和以后位置都放3都放不完调料了,跳出
边界3 优化 : 如果当前位置now>n 了,那表示再怎么放都不对了,跳出
处理 :这位放1 继续递归 这位放2 继续递归 这位放3 继续递归
思路很好理解,那就贴代码吗(呜呜当时调了很久 我好菜)
void pd(int pos,int now){
if(pos==10){ //边界1
if(now!=n)return;
ans++;
for(int i=1;i<=10;++i){
aa[ans][i]=cas[i]; //第ans种情况,先存起来
}
return ;
}
if(now>n)return ; //边界3
if(10-pos + now > n || (10-pos)*3 + now <n)return ; //边界2
cas[pos+1]=1; //这位放1 递归,下同理
pd(pos+1,now+1);
cas[pos+1]=2;
pd(pos+1,now+2);
cas[pos+1]=3;
pd(pos+1,now+3);
return ;
}
求个赞拉 写了这么多