P6386 [COCI 2007/2008 #4] VAUVAU

记录10

#include <bits/stdc++.h>
using namespace std;
bool f(int d1,int d2,int n){
	int t=n%(d1+d2);
	if(t<=d1&&t!=0) return true;
	else return false;  
} 
int main() {
	int a,b,c,d,n;
	cin>>a>>b>>c>>d;
	for(int i=1;i<=3;i++){
		cin>>n;
		bool x1=f(a,b,n);
		bool x2=f(c,d,n);
		int x=x1+x2;
		if(x==2) cout<<"both";
		else if(x==1) cout<<"one";
		else cout<<"none";
		cout<<endl;
	}
	return 0; 
}

突破点

其中一条狗会先暴躁 a 分钟,然后安静 b 分钟,而另一条狗则会先暴躁 c 分钟,然后安静 d 分钟。这两条狗在一天中会无限地重复上述行为。

所谓“无限地重复”,其本质就是有迹可循,像两个闹钟一样,响铃一会就自己关闭了

狗子处于 发癫-休息  的循环周期中

思路

  1. 两条狗的行为一样,只是参数不同,可用一个函数来模拟
  2. 三个工人挨个进行判断

狗子规律性地发癫跟休息,所以只需要判断工人来的时候,是不是在其发癫时刻就行

规律性的区间判断,可以使用取余%,取余的本质就是一种循环,在循环队列中有更明显的体现

文章的补充部分来解释下取余操作的本质是一种规律性的循环

代码简析

bool f(int d1,int d2,int n){
	int t=n%(d1+d2);
	if(t<=d1&&t!=0) return true;
	else return false;  
} 

d1狗子发癫时刻,d2狗子休息时刻,n为工人来的时刻

d1+d2 代表狗子在  发癫-休息  的循环周期

t代表目前狗子在  发癫-休息  这个循环周期的什么时刻

if(t<=d1&&t!=0)这个条件判断代表狗子处于发癫状态

注意:

对于全部的测试点,保证 1≤a,b,c,d,p,m,g<103。

数据是从1开始的

t=n%(d1+d2)代表狗子循环的周期,周期的尾巴是t=0此时是休息

if(t<=d1&&t!=0)这个条件判断代表狗子处于发癫状态

例子:

f(2,3,3)  //狗子在1到2时刻发癫,3的时候休息,工人在3的时候来了、

此时t=3%(2+3)       即t=3,也就是狗子处于休息时刻

t的范围:1,2,3,4,0

1,2是狗子发癫

3,4,0是休息

提醒:0的时候就是5或者5的倍数,此时处于狗子 发癫-休息 周期的尾巴,还在休息

        bool x1=f(a,b,n);
		bool x2=f(c,d,n);
		int x=x1+x2;

因为f函数是bool类型,所以用bool类型来接收

:bool类型在进行运算的时候,真为1,假为0

补充

取余操作(Modulo Operation)的本质确实是一种规律性的循环。这种规律性主要体现在取余操作的结果总是周期性地重复。

1. 取余操作的定义

取余操作 a % b 的结果是 a 除以 b 的余数。数学上,可以表示为: a=b×q+r 其中:

  • a 是被除数。

  • b 是除数。

  • q 是商。

  • r 是余数,满足 0≤r<b。

2. 规律性的循环

取余操作的结果总是周期性地重复,因为余数的范围是固定的。具体来说,对于任何整数 a 和正整数 b,余数 r 的范围是 0 到 b−1。

示例1:时钟问题

时钟是一个很好的例子,它展示了取余操作的周期性。假设现在是11点,再过2小时是1点。这是因为: (11+2)mod12=1

示例2:数组索引

在数组中,取余操作可以用来实现循环索引。假设有一个长度为5的数组,索引从0到4。如果当前索引是4,再往后移一位,索引应该是0。这是因为: (4+1)mod5=0

3. 数学解释

取余操作的周期性可以通过模运算的性质来解释。对于任何整数 a 和正整数 b,余数 r 满足: r=a mod b 其中 r 的范围是 0 到 b−1。

示例3:周期性重复

假设 b=5,取余操作的结果会周期性地重复:

  • 0mod5=0

  • 1mod5=1

  • 2mod5=2

  • 3mod5=3

  • 4mod5=4

  • 5mod5=0

  • 6mod5=1

  • 7mod5=2

  • 8mod5=3

  • 9mod5=4

  • 10mod5=0

可以看到,每5个数,结果就会重复一次。

4. 应用

取余操作的周期性在许多实际应用中非常有用,例如:

  • 时钟问题:计算时间的加法和减法。

  • 数组索引:实现循环数组,如循环队列。

  • 哈希表:计算哈希值,确保哈希值在表的范围内。

  • 周期性任务:调度周期性任务,如定时器。

5. 代码示例

以下是一个简单的C++代码示例,展示取余操作的周期性:

#include <iostream>
using namespace std;

int main() {
    int b = 5;
    for (int a = 0; a < 15; a++) {
        cout << a << " % " << b << " = " << a % b << endl;
    }
    return 0;
}

输出结果

0 % 5 = 0
1 % 5 = 1
2 % 5 = 2
3 % 5 = 3
4 % 5 = 4
5 % 5 = 0
6 % 5 = 1
7 % 5 = 2
8 % 5 = 3
9 % 5 = 4
10 % 5 = 0
11 % 5 = 1
12 % 5 = 2
13 % 5 = 3
14 % 5 = 4

总结

取余操作的本质是一种规律性的循环,因为余数的范围是固定的。这种周期性在许多实际应用中非常有用,例如时钟问题、数组索引、哈希表和周期性任务。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值