洛谷刷题(6)

 P4994 终于结束的起点

题目背景

终于结束的起点
终于写下句点
终于我们告别
终于我们又回到原点
……

一个个 OIer 的竞赛生涯总是从一场 NOIp 开始,大多也在一场 NOIp 中结束,好似一次次轮回在不断上演。
如果这次 NOIp 是你的起点,那么祝你的 OI 生涯如同夏花般绚烂。
如果这次 NOIp 是你的终点,那么祝你的 OI 回忆宛若繁星般璀璨。
也许这是你最后一次在洛谷上打比赛,也许不是。
不过,无论如何,祝你在一周后的比赛里,好运。

当然,这道题也和轮回有关系。

题目描述

广为人知的斐波拉契数列 fib(n) 是这么计算的

也就是 0,1,1,2,3,5,8,13⋯每一项都是前两项之和。

小 F 发现,如果把斐波拉契数列的每一项对任意大于 1 的正整数 M 取模的时候,数列都会产生循环。

当然,小 F 很快就明白了,因为 (fib(n−1) mod M)和 (fib(n−2) mod M) 最多只有 M*M 种取值,所以在 M*M次计算后一定出现过循环。

甚至更一般地,我们可以证明,无论取什么模数 MM,最终模 MM 下的斐波拉契数列都会是 0,1,⋯ ,0,1,⋯。

现在,给你一个模数 MM,请你求出最小的 n>0,使得 fib(n) mod M=0,fib(n+1) mod M=1。

输入格式

输入一行一个正整数 M。

输出格式

输出一行一个正整数 n。

代码

#include<stdio.h>  
  
// 定义模数m和用于存储斐波那契数列结果的数组f,数组大小足够大以存储所需的值  
long long m, f[10000030];  
  
// 递归函数,用于计算斐波那契数列的第x项模m的结果  
// 如果f[x]已经被计算过,则直接返回其值,否则递归计算并存储结果  
long long find(long long x) {  
    if (f[x]) return f[x]; // 如果f[x]已经被计算过,则直接返回其值  <-记忆化搜索
    if (x == 1 || x == 2) return f[x] = 1 % m; // 斐波那契数列的前两项都是1,取模m  
    else return f[x] = (find(x - 1) + find(x - 2)) % m; // 递归计算第x项的值,并取模m  
}  
  
int main() {  
    scanf("%lld", &m); // 读取模数m  
    long long i = 1; // 从斐波那契数列的第1项开始查找  
  
    // 循环查找,直到找到第一个斐波那契数列中相邻的两项,使得第i项模m为0,且第i+1项模m为1  
    while (find(i) != 0 || find(i + 1) != 1) {  
        i++; // 如果当前项不满足条件,则检查下一项  
    }  
  
    printf("%lld", i); // 输出满足条件的最小项数i  
    return 0;  
}

P1059 [NOIP2006 普及组] 明明的随机数

题目描述

明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了 N 个 1 到 1000 之间的随机整数 (N≤100),对于其中重复的数字,只保留一个,把其余相同的数去掉,不同的数对应着不同的学生的学号。然后再把这些数从小到大排序,按照排好的顺序去找同学做调查。请你协助明明完成“去重”与“排序”的工作。

输入格式

输入有两行,第 1 行为 1 个正整数,表示所生成的随机数的个数 N。

第 2 行有 N 个用空格隔开的正整数,为所产生的随机数。

输出格式

输出也是两行,第 1 行为 1 个正整数 M,表示不相同的随机数的个数。

第 2 行为 M 个用空格隔开的正整数,为从小到大排好序的不相同的随机数。

代码

#include<stdio.h>  
  
// 定义一个全局变量count,用于记录不同数字的数量  
int count = 0;  
  
// 定义全局变量n用于存储将要输入的数的个数,a用于临时存储每次读入的数,b数组用于记录哪些数字已经出现过  
int n, a, b[1200];  
  
int main() {  
    // 读取将要输入的数的个数  
    scanf("%d", &n);  
  
    // 循环读取n个数  
    for (int i = 0; i < n; i++) {  
        // 读取一个数到变量a中  
        scanf("%d", &a);  
  
        // 检查这个数(a)是否已经在b数组中记录过(即b[a]是否为0),如果是,说明这是第一次遇到这个数  
        if (b[a] == 0) {  
            // 如果是第一次遇到,则增加count的值  
            count++;  
        }  
  
        // 无论是否是第一次遇到,都将b[a]设为1,表示这个数已经被记录过了  
        b[a] = 1;  
    }  
  
    // 打印不同数字的数量  
    printf("%d\n", count);  
  
    // 循环遍历b数组,打印出所有出现过的数字(即b[i]为1的i值)  
    for (int i = 0; i < 1200; i++) {  
        if (b[i] == 1) {  
            printf("%d ", i);  
        }  
    }  
  
    // 程序正常结束  
    return 0;  
}

P1179 [NOIP2010 普及组] 数字统计

题目描述

请统计某个给定范围 [L,R] 的所有整数中,数字 2 出现的次数。

比如给定范围 [2,22],数字 2 在数 2 中出现了 1 次,在数 12 中出现 1 次,在数 20 中出现 1 次,在数 21 中出现 1 次,在数 22 中出现 2 次,所以数字 2 在该范围内一共出现了 6 次。

输入格式

2 个正整数 L 和 R,之间用一个空格隔开。

输出格式

数字 2 出现的次数。

代码

#include<stdio.h>  
  
// 定义一个全局变量来记录包含数字2的数的个数  
int count;  
  
int main() {  
    int a, b;  
    // 读取用户输入的两个整数  
    scanf("%d%d", &a, &b);  
      
    int t, f; // t用于存储f除以10的余数,f用于在循环中遍历当前数字  
      
    // 使用for循环遍历从a到b(包含a和b)的所有整数  
    for (int i = a; i <= b; i++) {  
        f = i; // 将当前整数赋值给f,用于接下来的位检查  
          
        // 使用while循环来检查当前整数f的每一位是否包含数字2  
        while (f != 0) {  
            t = f % 10; // 取出f的最后一位  
            if (t == 2) count++; // 如果最后一位是2,则计数器加1  
            f /= 10; // 去掉f的最后一位,继续检查下一位  
        }  
    }  
      
    // 输出结果:在给定的两个整数之间,包含数字2的数的个数  
    printf("%d", count);  
      
    return 0;  
}

P9231 [蓝桥杯 2023 省 A] 平方差

题目描述

给定 L,R,问 L≤x≤R 中有多少个数 x 满足存在整数 y,z 使得 x=y^2−z^2。

输入格式

输入一行包含两个整数 L,R,用一个空格分隔。

输出格式

输出一行包含一个整数满足题目给定条件的 x 的数量。

代码

#include<stdio.h>

int hans1(int x) {
	if (x == 0)return 0;
	return (x + 1) / 2;
}

int hans2(int x){
	return x / 4;
}
int main() {
	int a, b;
	scanf("%d%d", &a, &b);
	printf("%d", hans1(b) + hans2(b) - hans1(a - 1) - hans2(a - 1));
	return 0;
}

 今天的算法题完成啦

  • 13
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值