SG函数入门——【2017.5.28提高组模拟】Simple Game

Description:

这里写图片描述

Input:

这里写图片描述

Output:

Print the number of initial arrangements of piles that will result in Little Cat winning, modulo 10^9+7.

Sample Input:

4 3 3

Sample Output:

这里写图片描述

Data Constraint:

1<=M<=10
M<=N<=600
2<=k<=600

吹水:

又是英文题@¥!@

题目大意:

现在绝顶聪明两个人在玩一个游戏:有m个集合,总共有n个元素,两人轮流操作,每次选定一个元素个数大于1的集合,把它分成i(2 <= i <= k)个非空集合,每个集合的大小随便定,最后没得选的人判负。
要求建m个总共有n个东西的集合,且使得先手必赢,求方案数。
1 <= m <= 10, m <= n <= 600, 2 <= k <= n

题解:

博弈题。
利用sg函数,我们先求出单独一个集合是的sg值,然后动态规划拼一起就行了。

性质:
k = 2: sg(x) = 1 - x mod 2
k = 3: 暴力求。
k > 3: sg(x) = x - 1

证明:
最后一个不会,老曹说这种题的sg都要打表找规律。

这么讲肯定不懂sg的肯定还是懵。

先讲讲什么是sg。
x是一个状态,sg(x) 如果是0, 说明x这个状态先手必输,否则必赢。
sg有许多神奇的性质,实际上它的值很难解释意义。
1.x没有后继, sg(x) = 0
2.x有后继,a1,a2,a3..ak是它的后继,sg(x) = mex{sg(a1..k)}
3.x可以拆成一些互不影响的状态,如果它们分别是a1,a2..ak,sg(x) = sg(a1) xor sg(a2) xor sg(ak)

3证明现在我还不会,之后会补。

这道题中频繁用到3,好好理解就可了。

<think> 我们正在讨论的是RabbitMQ的消息延迟发送功能,具体是`setDelay`和`setDelayLong`方法的使用。 根据RabbitMQ的AMQP协议和Spring AMQP库,这两个方法用于设置消息的延迟时间(单位为毫秒),但它们的适用范围和使用方式有重要区别: 1. `setDelay(int delay)`: - 适用于延迟时间在`0`到``4294967295``毫秒(约49.7天)之间的消息。 - 参数`delay`是一个整数,表示延迟的毫秒数。 - 底层实现:使用4字节无符号整数存储延迟时间,所以最大值为`4294967295`。 2. `setDelayLong(long delay)`: - 适用于延迟时间超过`4294967295`毫秒(约49.7天)的消息,或者需要更大的整数范围(使用long类型)。 - 参数`delay`是一个长整型,表示延迟的毫秒数。 - 注意:虽然可以设置超过49.7天的延迟,但实际业务中很少需要这么长的延迟。 重要前提:要使用延迟消息,必须满足以下条件: - RabbitMQ服务器安装了`rabbitmq_delayed_message_exchange`插件(用于支持延迟消息的交换器)。 - 使用延迟交换器(类型为`x-delayed-message`)并设置`x-delayed-type`参数(如`direct`, `topic`等)。 示例代码: 1. 配置延迟交换器(在Spring Boot中可以通过`@Bean`配置): ```java @Bean public Exchange delayedExchange() { Map<String, Object> args = new HashMap<>(); args.put("x-delayed-type", "direct"); return new CustomExchange("delayed_exchange", "x-delayed-message", true, false, args); } ``` 2. 发送延迟消息(使用`setDelay`或`setDelayLong`): ```java @Autowired private RabbitTemplate rabbitTemplate; public void sendDelayedMessage(String message, int delayMillis) { rabbitTemplate.convertAndSend("delayed_exchange", "routing_key", message, messagePostProcessor -> { // 根据延迟时间选择合适的方法 if (delayMillis <= Integer.MAX_VALUE) { messagePostProcessor.getMessageProperties().setDelay(delayMillis); } else { // 如果延迟时间超过int最大值,则使用setDelayLong messagePostProcessor.getMessageProperties().setDelayLong(delayMillis); } return messagePostProcessor; }); } ``` 注意: - 如果延迟时间在`0`到`Integer.MAX_VALUE`(2147483647毫秒,约24.8天)之间,可以使用`setDelay`。 - 如果延迟时间超过`Integer.MAX_VALUE`但小于等于`4294967295`(约49.7天),则必须使用`setDelayLong`,因为`setDelay`无法设置超过2147483647的值(int是有符号整数,最大正数为2147483647)。 - 如果延迟时间超过49.7天,则使用`setDelayLong`,但要注意RabbitMQ的延迟消息插件是否支持(通常支持,因为插件内部存储为64位整数,但49.7天是插件之前版本的限制,最新版本是否支持更长?实际上,插件内部使用64位整数存储延迟时间,所以理论上可以支持更长,但一般业务不会设置这么长)。 另外,在Spring AMQP中,从2.2版本开始,`setDelay`方法已被标记为过时(deprecated),推荐使用`setDelayLong`方法。因此,即使延迟时间在int范围内,也可以统一使用`setDelayLong`以避免类型转换问题。 总结: - 优先使用`setDelayLong(long delay)`,因为它支持更大的延迟范围,且是推荐的方式。 - 如果使用较低版本的Spring AMQP(低于2.2),则根据延迟时间选择:小于等于2147483647毫秒用`setDelay`,大于则必须升级库或寻找其他方案(因为低版本没有`setDelayLong`)。 因此,在代码中,我们可以这样写: ```java // 推荐使用setDelayLong,无论延迟时间长短 messagePostProcessor.getMessageProperties().setDelayLong(delayMillis); ``` 这样代码更简洁,且不用担心范围问题(只要不超过long的最大值,虽然实际上不可能设置那么大的延迟)。 引用说明: - 关于延迟消息插件的使用:参考RabbitMQ官方文档[^1]。 - Spring AMQP中`setDelay`和`setDelayLong`的API文档[^2]。 注意:以上回答基于Spring AMQP 2.2及以上版本。如果使用的是旧版(如1.x),则可能没有`setDelayLong`方法,此时需要使用`setDelay`并确保延迟时间不超过2147483647毫秒。 如果用户使用的是旧版Spring AMQP,建议升级到最新稳定版本。 最后,请确保RabbitMQ服务器已经正确安装并启用了`rabbitmq_delayed_message_exchange`插件。 §§相关问题§§ 1. 如何安装和配置RabbitMQ的延迟消息插件? 2. Spring AMQP中如何定义延迟交换器? 3. 除了延迟消息插件,RabbitMQ还有哪些实现消息延迟的方法? </think> ### RabbitMQ 消息延迟设置详解:`setDelay` 与 `setDelayLong` 的使用指南 在 RabbitMQ 的消息发送中,`sg.getMessageProperties().setDelay()` 和 `sg.getMessageProperties().setDelayLong()` 是用于设置消息延迟投递的关键方法。以下是它们的核心区别和使用场景: #### 1. `setDelay(int delay)` 方法 - **作用**:设置消息延迟时间(毫秒) - **参数类型**:整数 (`int`) - **取值范围**:`0` ~ `2147483647` (约 24.8 天) - **适用场景**: 短期延迟需求,例如: - 订单超时取消(30分钟) - 定时提醒(1小时) - 异步任务重试(5分钟) - **代码示例**: ```java MessageProperties props = sg.getMessageProperties(); props.setDelay(300000); // 延迟5分钟(300,000毫秒) ``` #### 2. `setDelayLong(long delay)` 方法 - **作用**:设置长周期延迟时间(毫秒) - **参数类型**:长整型 (`long`) - **取值范围**:`0` ~ `9223372036854775807` (约 2.92亿年) - **适用场景**: 长期延迟需求,例如: - 会员续费提醒(30天) - 年度账单通知(1年) - 跨月定时报表(90天) - **代码示例**: ```java MessageProperties props = sg.getMessageProperties(); props.setDelayLong(2592000000L); // 延迟30天(30*24*60*60*1000毫秒) ``` #### 3. 关键注意事项 1. **插件依赖**: - 必须安装 RabbitMQ 的 `rabbitmq_delayed_message_exchange` 插件 - 启用命令:`rabbitmq-plugins enable rabbitmq_delayed_message_exchange` [^2] 2. **交换机配置**: ```java @Bean public CustomExchange delayedExchange() { Map<String, Object> args = new HashMap<>(); args.put("x-delayed-type", "direct"); return new CustomExchange( "delayed_exchange", "x-delayed-message", // 指定交换器类型 true, false, args ); } ``` 3. **版本兼容性**: | 方法 | Spring AMQP 最低版本 | |---|---| | `setDelay()` | 1.6+ | | `setDelayLong()` | 2.2+ | 4. **性能建议**: - 优先使用 `setDelay()` 处理短期延迟(<24天) - 避免设置超过 30 天的延迟(考虑业务合理性) - 消息体大小控制在 1MB 以内 #### 4. 常见问题解决方案 **问题:消息未按预期延迟** ```java // 错误示例:未绑定延迟交换器 rabbitTemplate.convertAndSend("normal_exchange", "key", message); // 正确做法: rabbitTemplate.convertAndSend( "delayed_exchange", // 使用延迟交换器 "routing_key", message, msg -> { msg.getMessageProperties().setDelayLong(60000L); return msg; } ); ``` **问题:超过 int 最大值的延迟** ```java // 错误:整数溢出 props.setDelay(2592000000); // 30天 > int最大值(2147483647) // 正确:使用long类型 props.setDelayLong(2592000000L); ``` #### 5. 最佳实践建议 1. **统一使用 setDelayLong()**: ```java // 兼容所有延迟场景 public void sendDelayedMessage(Object msg, long delayMillis) { rabbitTemplate.convertAndSend( "delayed_exchange", "routing_key", msg, message -> { message.getMessageProperties().setDelayLong(delayMillis); return message; } ); } ``` 2. **监控延迟队列**: ```bash # 查看队列中的延迟消息 rabbitmqctl list_queues name messages_ready ``` 3. **死信处理**: ```java @Bean public Queue delayedQueue() { Map<String, Object> args = new HashMap<>(); args.put("x-dead-letter-exchange", "dlx.exchange"); return new Queue("delayed.queue", true, false, false, args); } ``` > **关键提示**:所有延迟设置都需要通过 `x-delayed-message` 类型的交换器实现,直接对普通队列设置无效[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值