小明带两个妹妹参加元宵灯会。别人问她们多大了,她们调皮地说:“我们俩的年龄之积是年龄之和的6倍”。小明又补充说:“她们可不是双胞胎,年龄差肯定也不超过8岁啊。”
请你写出:小明的较小的妹妹的年龄。
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int main(){
for(int i=1;i<=20;i++){
for(int j=i;j<=i+8;j++){
if(i*j==6*(i+j)){
cout<<i<<' '<<j<<endl;
return 0;
}
}
}
}
//10
3.神奇算式
由4个不同的数字,组成的一个乘法算式,它们的乘积仍然由这4个数字组成。
比如:
210 x 6 = 1260
8 x 473 = 3784
27 x 81 = 2187 都符合要求。
如果满足乘法交换律的算式算作同一种情况,那么,包含上边已列出的3种情况,一共有多少种满足要求的算式。
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int judge(int a,int b,int c){
int count=0;
int book[10];
memset(book,0,sizeof(book));
if(c<=1000||c>=10000){
return 0;
}
while(a){
if(book[a%10]){
return 0;
}
book[a%10]=1;
count++;
a/=10;
}
while(b){
if(book[b%10]){
return 0;
}
book[b%10]=1;
count++;
b/=10;
}
if(count!=4){
return 0;
}
while(c){
if(!book[c%10]){
return 0;
}
book[c%10]=0;
c/=10;
}
return 1;
}
int main(){
int a[4];
int num1,num2,count=0;
for(num1=1;num1<=100;num1++){
for(num2=num1+1;num2<=9999;num2++){
if(judge(num1,num2,num1*num2)){
count++;
}
}
}
cout<<count<<endl;
return 0;
}
//12
5.锦标赛
如果要在n个数据中挑选出第一大和第二大的数据(要求输出数据所在位置和值),使用什么方法比较的次数最少?我们可以从体育锦标赛中受到启发。
如图【1.png】所示,8个选手的锦标赛,先两两捉对比拼,淘汰一半。优胜者再两两比拼...直到决出第一名。
第一名输出后,只要对黄色标示的位置重新比赛即可。
下面的代码实现了这个算法(假设数据中没有相同值)。
代码中需要用一个数组来表示图中的树(注意,这是个满二叉树,不足需要补齐)。它不是存储数据本身,而是存储了数据的下标。
第一个数据输出后,它所在的位置被标识为-1
//重新决出k号位置,v为已输出值
void pk(int* a, int* b, int n, int k, int v){
int k1 = k*2 + 1;
int k2 = k1 + 1;
if(k1>=n || k2>=n){
b[k] = -1;
return;
}
if(b[k1]==v)
pk(a,b,n,k1,v);
else
pk(a,b,n,k2,v);
//重新比较
if(b[k1]<0){
if(b[k2]>=0)
b[k] = b[k2];
else
b[k] = -1;
return;
}
if(b[k2]<0){
if(b[k1]>=0)
b[k] = b[k1];
else
b[k] = -1;
return;
}
if(______________________) //填空
b[k] = b[k1];
else
b[k] = b[k2];
}
//对a中数据,输出最大,次大元素位置和值
void f(int* a, int len){
int n = 1;
while(n<len) n *= 2;
int* b = (int*)malloc(sizeof(int*) * (2*n-1));
int i;
for(i=0; i<n; i++){
if(i<len)
b[n-1+i] = i;
else
b[n-1+i] = -1;
}
//从最后一个向前处理
for(i=2*n-1-1; i>0; i-=2){
if(b[i]<0){
if(b[i-1]>=0)
b[(i-1)/2] = b[i-1];
else
b[(i-1)/2] = -1;
}
else{
if(a[b[i]]>a[b[i-1]])
b[(i-1)/2] = b[i];
else
b[(i-1)/2] = b[i-1];
}
}
//输出树根
printf("%d : %d\n", b[0], a[b[0]]);
//值等于根元素的需要重新pk
pk(a,b,2*n-1,0,b[0]);
//再次输出树根
printf("%d : %d\n", b[0], a[b[0]]);
free(b);
}
int main(){
int a[] = {54,55,18,16,122,17,30,9,58};
f(a,9);
}
//答案:a[b[k1]]>=a[b[k2]]
6.扑克序列
A A 2 2 3 3 4 4, 一共4对扑克牌。请你把它们排成一行。要求:两个A中间有1张牌,两个2之间有2张牌,两个3之间有3张牌,两个4之间有4张牌。
请填写出所有符合要求的排列中,字典序最小的那个。例如:22AA3344 比 A2A23344 字典序小。当然,它们都不是满足要求的答案。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
int judge(int c[],int a,int b){
int i,j,loc1,loc2;
for(i=0;i<8;i++){
if(c[i]==a){
loc1=i;
break;
}
}
for(j=i+1;j<8;j++){
if(c[j]==a){
loc2=j;
break;
}
}
if(loc2-loc1==b+1){
return 1;
}
return 0;
}
int main(){
int a[8]={2,2,3,3,4,4,5,5};
do{
if(judge(a,5,1)&&judge(a,2,2)&&judge(a,3,3)&&judge(a,4,4)){
break;
}
}while(next_permutation(a,a+8));
for(int i=0;i<8;i++){
printf("%d",a[i]);
}
cout<<endl;
return 0;
}
//23425354 题目的意思为字母的字典序大
//即:2342A3A4
9.标题:斐波那契
斐波那契数列大家都非常熟悉。它的定义是:
f(x) = 1 .... (x=1,2)
f(x) = f(x-1) + f(x-2) .... (x>2)
对于给定的整数 n 和 m,我们希望求出:
f(1) + f(2) + ... + f(n) 的值。但这个值可能非常大,所以我们把它对 f(m) 取模。
但这个数字依然很大,所以需要再对 p 求模。
【数据格式】
输入为一行用空格分开的整数 n m p (0 < n, m, p < 10^18)
输出为1个整数
例如,如果输入:
2 3 5
程序应该输出:
0
再例如,输入:
15 11 29
程序应该输出:
25
//目前只过了部分测试点......待完善
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
typedef long long LL;
LL n,m,p,MOD,re;
struct node{
int m[2][2];
};
struct node Cal(struct node a,struct node b){
struct node c;
memset(c.m,0,sizeof(c.m));
for(int i=0;i<2;i++){
for(int j=0;j<2;j++){
if(a.m[i][j]){
for(int t=0;t<2;t++){
c.m[i][t]=c.m[i][t]+a.m[i][j]*b.m[j][t];
}
}
}
}
return c;
}
struct node quick_pow(struct node a,LL cnt){
struct node e;
memset(e.m,0,sizeof(e.m));
e.m[0][0]=e.m[1][1]=1;
if(cnt==0){
return e;
}
if(cnt==1){
return a;
}
while(cnt){
if(cnt&1){
e=Cal(e,a);
}
a=Cal(a,a);
cnt=cnt>>1;
}
return e;
}
int main(){
LL top;
struct node mat,t;
scanf("%lld%lld%lld",&n,&m,&p);
mat.m[0][1]=mat.m[1][0]=mat.m[1][1]=1;
mat.m[0][0]=0;
t=quick_pow(mat,m-1);
MOD=t.m[0][0]+t.m[0][1];
for(LL i=1;i<=n;i++){
t=quick_pow(mat,i-1);
re=(re+t.m[0][0]+t.m[0][1])%MOD;
}
printf("%lld\n",re%p);
return 0;
}
10.波动数列
观察这个数列:1 3 0 2 -1 1 -2 ...
这个数列中后一项总是比前一项增加2或者减少3。
栋栋对这种数列很好奇,他想知道长度为 n 和为 s 而且后一项总是比前一项增加a或者减少b的整数数列可能有多少种呢?
【数据格式】
输入的第一行包含四个整数 n s a b,含义如前面说述。
输出一行,包含一个整数,表示满足条件的方案数。由于这个数很大,请输出方案数除以100000007的余数。
例如,输入:
4 10 2 3
程序应该输出:
2
【样例说明】
这两个数列分别是2 4 1 3和7 4 1 -2。
【数据规模与约定】
对于10%的数据,1<=n<=5,0<=s<=5,1<=a,b<=5;
对于30%的数据,1<=n<=30,0<=s<=30,1<=a,b<=30;
对于50%的数据,1<=n<=50,0<=s<=50,1<=a,b<=50;
对于70%的数据,1<=n<=100,0<=s<=500,1<=a, b<=50;
对于100%的数据,1<=n<=1000,-1,000,000,000<=s<=1,000,000,000,1<=a, b<=1,000,000。
//动态规划
待写......
可见,A组编程大题的后一两道还是比较难的,对于B组选手来说确实要下功夫才能和211,985的大牛们相比......