学习日记/2/14坏日子

可恶,要开学了,好烦,来点题目压压惊吧

题目背景

本题为提交答案题,您可以写程序或手算在本机上算出答案后,直接提交答案文本,也可提交答案生成程序。

题目描述

将 1, 2, \ldots , 91,2,…,9 共 99 个数分成 33 组,分别组成 33 个三位数,且使这 33 个三位数构成 1 : 2 : 31:2:3 的比例,试求出所有满足条件的 33 个三位数。

输入格式

输出格式

若干行,每行 33 个数字。按照每行第 11 个数字升序排列。

输入输出样例

输入 #1复制

输出 #1复制

192 384 576
* * *
...

* * *
(剩余部分不予展示)

这题目,理解倒是,好理解,当然代码也不难,一看到,每个数字用一次,满足特定的条件输出脑袋就闪过了,dfs

全排序一次,满足的就输出,纯纯的暴力,这题目要的是答案过程,时间无伤大雅

#include<stdio.h>
int map[15];
int ans[10];
int i=1;

void dfs(int l){
if(l==10){
    if(2*(ans[1]*100+ans[2]*10+ans[3])==ans[4]*100+ans[5]*10+ans[6]&&3*(ans[1]*100+ans[2]*10+ans[3])==ans[7]*100+ans[8]*10+ans[9]){
        printf("%d%d%d %d%d%d %d%d%d\n",ans[1],ans[2],ans[3],ans[4],ans[5],ans[6],ans[7],ans[8],ans[9]);
    }

}
else{
    for(int y=1;y<=9;y++){
        if(map[y]==0){
            ans[i]=y;
            map[y]=1;
            i++;
            dfs(i);
            map[y]=0;
            i--;
        }
    }
}


}

int main(){

printf("192 384 576\n");
printf("219 438 657\n");
printf("273 546 819\n");
printf("327 654 981\n");



return 0;
}

上面是dfs的函数,下面是用dfs求得得答案

没有一点问题

代码嘎嘎短 

下一个

题目描述

用高精度计算出 S = 1! + 2! + 3! + \cdots + n!S=1!+2!+3!+⋯+n!(n \le 50n≤50)。

其中 ! 表示阶乘,定义为 n!=n\times (n-1)\times (n-2)\times \cdots \times 1n!=n×(n−1)×(n−2)×⋯×1。例如,5! = 5 \times 4 \times 3 \times 2 \times 1=1205!=5×4×3×2×1=120。

输入格式

一个正整数 nn。

输出格式

一个正整数 SS,表示计算结果。

输入输出样例

输入 #1复制

3

输出 #1复制

9

说明/提示

【数据范围】

对于 100 \%100% 的数据,1 \le n \le 501≤n≤50。

【其他说明】

注,《深入浅出基础篇》中使用本题作为例题,但是其数据范围只有 n \le 20n≤20,使用书中的代码无法通过本题。

如果希望通过本题,请继续学习第八章高精度的知识。

出自:P1009 [NOIP1998 普及组] 阶乘之和 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

这题目就是要用高精度方法去求

就是把一个数当成一位(每位最大不可以大于9的)

当成10进制就欧克了

边看代码边理解

#include<stdio.h>

int a[10005],b[10005];//b保留阶乘,a保留阶乘和
int i=1;
int l=1;//这个留阶乘与阶乘和的位数

int main(){
int n;
scanf("%d",&n);
a[1]=1;
b[1]=1;//初始化
for(int j=2;j<=n;j++){
        int lj=i;
    for(int h=1;h<=lj;h++){//先算j的阶乘b的值
        b[h]=b[h]*j;
    }

        for(int h=1;h<=i;h++){//满10以上要进位
            if(b[h]>=10){
                b[h+1]=b[h+1]+b[h]/10;
                b[h]=b[h]%10;
                if(h==i){
                    b[i+1]=b[i+1]+b[i]/10;
                    b[i]=b[i]%10;
                    i++;
                }
            }
        }
        if(l<i){//阶乘和的位数不可能比阶乘小的
            l=i;
        }
    for(int kl=1;kl<=i;kl++){//每位相加依然是满10进位但是由于是加法所以不会超过20 可以用a[l+1]++
            a[kl]+=b[kl];
            if(a[kl]>=10){
                a[kl]=a[kl]%10;
                a[kl+1]++;
            }
    }
     if(a[l]>=10){//对最后的一位检查要是大于10就进位
            a[l]=a[l]%10;
            a[l+1]++;
            l++;
        }
}
for(int y=l;y>=1;y--){//用记录的位数从尾往前输出
    printf("%d",a[y]);
}


return 0;
}

就是要有一个变量当一位数的思想,剩下的就是简单的加法和乘法了,以及满10进一的原则了

题目不难就是学点东西就可以了

ok下一个 

题目描述

火车从始发站(称为第 11 站)开出,在始发站上车的人数为 aa,然后到达第 22 站,在第 22 站有人上、下车,但上、下车的人数相同,因此在第 22 站开出时(即在到达第 33 站之前)车上的人数保持为 aa 人。从第 33 站起(包括第 33 站)上、下车的人数有一定规律:上车的人数都是前两站上车人数之和,而下车人数等于上一站上车人数,一直到终点站的前一站(第 (n-1)(n−1) 站),都满足此规律。现给出的条件是:共有 nn 个车站,始发站上车的人数为 aa ,最后一站下车的人数是 mm(全部下车)。试问 xx 站开出时车上的人数是多少?

输入格式

输入只有一行四个整数,分别表示始发站上车人数 aa,车站数 nn,终点站下车人数 mm 和所求的站点编号 xx。

输出格式

输出一行一个整数表示答案:从 xx 站开出时车上的人数。

输入输出样例

输入 #1复制

5 7 32 4

输出 #1复制

13

说明/提示

对于全部的测试点,保证 1 \leq a \leq 201≤a≤20,1 \leq x \leq n \leq 201≤x≤n≤20,1 \leq m \leq 2 \times 10^41≤m≤2×104。

 

这题目,可太数学了

呜呜呜呜呜呜呜

我真的是无语,纯纯的数学题目

有个未知数就是在2站到底上了多少人

我们设为x

在本子上推导

每个站点增加的人数

a1=a;

a2=0;

a3=a;

a4=x;

a5=a+x;

a6=a+2x;

从推导可以看出从第5站后面人数就是一个斐波那契数列了

但是x是未知数,所以我们的任务就是求出x,但是程序不会公式,我们要想办法去实现

而且a和x要分开来求系数

呜呜呜,明明答案就在我的眼前但是我就是拿不到

上代码

出自:P1011 [NOIP1998 提高组] 车站 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include<stdio.h>
int a[100];
int find(int hj){//这里是求x的系数
int u=0;
a[1]=0;
a[2]=0;
a[3]=0;
a[4]=1;
if(hj>4){
    u++;
}
for(int jk=5;jk<hj;jk++){
    a[jk]=a[jk-1]+a[jk-2];
    u+=a[jk];
}
return u;
}


int main(){
int n;
int x;
int l;
int ans;
scanf("%d%d%d%d",&x,&n,&l,&ans);
int jk=find(n);
a[1]=0;
a[2]=0;
a[3]=1;
a[4]=0;
int lk=1;
if(n>3){
    lk++;
}
for(int g=5;g<n;g++){//这里是求a的系数
    a[g]=a[g-1]+a[g-2];
    lk+=a[g];
}//两个系数到手解方程就可以了
int hj=l-x*lk;
int v=hj/jk;

int sum=x;
a[3]=x;
a[4]=v;
if(ans>=3){//得到了x就从新求一边得出答案
    sum+=x;
}
if(ans>=4){
    sum+=v;
}
for(int bn=5;bn<=ans;bn++){
    a[bn]=a[bn-1]+a[bn-2];
    sum+=a[bn];
}
printf("%d",sum);

return 0;

}

这是极少数,我感觉用程序比实际去解还要麻烦的现实问题。 

肯定是我的方法有问题一定是的。
要是身边没有一支笔一个本子,我想这题目的难度还要上升几个档次 
ok下一个

题目描述

任何一个正整数都可以用 22 的幂次方表示。例如 137=2^7+2^3+2^0137=27+23+20。

同时约定方次用括号来表示,即 a^bab 可表示为 a(b)a(b)。

由此可知,137137 可表示为 2(7)+2(3)+2(0)2(7)+2(3)+2(0)

进一步:

7= 2^2+2+2^07=22+2+20 ( 2^121 用 22 表示),并且 3=2+2^03=2+20。

所以最后 137137 可表示为 2(2(2)+2+2(0))+2(2+2(0))+2(0)2(2(2)+2+2(0))+2(2+2(0))+2(0)。

又如 1315=2^{10} +2^8 +2^5 +2+11315=210+28+25+2+1

所以 13151315 最后可表示为 2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)。

输入格式

一行一个正整数 nn。

输出格式

符合约定的 nn 的 0, 20,2 表示(在表示中不能有空格)。

输入输出样例

输入 #1复制

1315

输出 #1复制

2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)

说明/提示

【数据范围】

对于 100\%100% 的数据,1 \le n \le 2 \times {10}^41≤n≤2×104。

出自:P1010 [NOIP1998 普及组] 幂次方 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

本来是想老老实实的用dfs来写的可是看到数据确实不大,ok邪恶的想法出现了,

先打表,然后输出,数据很小,那笔写一写就可以了真的不要太爽

#include<stdio.h>

int main(){
char a[16][100]={"2(0)","2","2(2)","2(2+2(0))","2(2(2))","2(2(2)+2(0))","2(2(2)+2)","2(2(2)+2+2(0))","2(2(2+2(0)))","2(2(2+2(0))+1)","2(2(2+2(0))+2)","2(2(2+2(0))+2+2(0))","2(2(2+2(0))+2(2))","2(2(2+2(0))+2(2)+2(0))","2(2(2+2(0))+2(2)+2)","2(2(2+2(0))+2(2)+2+2(0))"};
int n;
int map[15]={1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384};
scanf("%d",&n);
for(int h=14;h>=0;h--){

    if(n>=map[h]){
        n=n-map[h];
        printf("%s",a[h]);
        if(n!=0){
            printf("+");
        }
        else{
            break;
        }
    }

}
return 0;
}

打表yyds

变成二进制完全没有问题,在加上提前备好的输出,直接秒杀

ok今天就到这把

我直接开溜!

byebye!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值