Agc010_D Decrementing

本文分析了一款涉及数学策略的游戏题目,其中包含最大公约数及奇偶性的运用。游戏由Alice和Bob参与,通过一系列操作决出胜负。文章详细解释了如何通过算法判断先手是否必胜,并提供了具体实现代码。

今天本人因调了上篇博客的题而脑壳不适,不想颓题,因此有了这篇博客。

但是博客毕竟得讲点什么,想想有没有什么代码短的。

哦,好像有,就Agc010_D Decrementing好了。

 

Alice和Bob又在玩游戏了,这次他们有$N$个数。

每次操作为:
1.在所有不小于$2$的数中挑一个减去$1$。
2.所有数除$d$,$d$为所有数的最大公约数。
不能操作者输,如果先手必胜则输入$First$,否则输出$Second$。

其中$N\leq 10^5$,每个数$\leq 10^9$。

 

乍一看令人十分懵逼,但是我们很容易的发现有几个显然测结论:

1、当最小的数是1时,胜负至于所有数之和$-N$的奇偶性有关

2、有效的除$d$操作不超过$log_210^9=30$次。

我们先定义奇偶性优势:按照每一步操作恰好改变一次奇偶性,最终能获取胜利(即自己操作时有奇数个偶数)。

奇偶性劣势则反之。

然后进一步思考,对于当前操作的人:

若当前的和奇偶性状况对自己有利,则尽量这一奇偶性不改变。我们显然能找到奇数个偶数,对任意一个进行操作之后,$d$一定是个奇数,因此除$d$操作对奇偶性没有影响,并且原先的偶数不会变成奇数,并且会新产生一个奇数。由于任意操作完的局面不可能全是偶数(保证$gcd=1$),因此后手操作的人一定面对至少$2$个奇数,而奇数的数量只会一直增加,因而无论怎么操作$d$均为奇数都无法改变奇偶性劣势,因此必胜。

若当前自己处在奇偶性劣势,则必须考虑通过除$d$操作改变奇偶性。我们发现,这一操作能够实现仅当所有剩余的数中有且仅有一个奇数,且这一奇数大于$1$时才有可能。我们不得不对这个数进行操作,因此会先把原来的奇数减去$1$,使得所有数都为偶数,再新产生至少$1$个奇数。这时我们并不能确定获胜情况,因此我们需要递归地进入下一层。

由于结论$2$,最多会出现$30$层,每层只需要扫一遍,因此最终复杂度是$O(n\space log A_i)$。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define M 100050
using namespace std;
LL read(){
	LL nm=0,fh=1; char cw=getchar();
	for(;!isdigit(cw);cw=getchar()) if(cw=='-') fh=-fh;
	for(;isdigit(cw);cw=getchar()) nm=nm*10+(cw-'0');
	return nm*fh;
}
LL gcd(LL x,LL y){return y==0?x:gcd(y,x%y);}
LL n,p[M],G[M],F[M],sq[31];
void win(LL x){puts(x?"Second":"First");exit(0);}
void solve(LL now){
	LL pos=0,sum=0,m=0,tot=0;
	for(LL i=1;i<=n;i++) sum+=p[i],m+=(p[i]&1),pos+=(p[i]&1)*i;
	if((sum&1)^(n&1)) win(now);
	else if((m==1&&p[pos]==1)||m>1) win(now^1);
	for(LL i=1;i<=n;i++) tot=gcd(tot,p[i]-(p[i]&1));
	for(LL i=1;i<=n;i++) p[i]=(p[i]-(p[i]&1))/tot;
	solve(now^1);
}
int main(){
	n=read(),sq[0]=1;
	for(LL i=1;i<31;i++) sq[i]=sq[i-1]*2ll;
	for(LL i=1;i<=n;i++) p[i]=read();
	sort(p+1,p+n+1),solve(0);
	return 0;
}

  

转载于:https://www.cnblogs.com/OYJason/p/9629995.html

给这个代码加上适量的英文注释。module dtp_fil ( input wire clk , input wire rst_n , input wire fil_en , input wire [2:0] fil_id , input wire [7:0] fil_data , input wire fil_qos , input wire fil_pre_eop, input wire arb_en , output wire buf_vld , output reg [2:0] buf_id , output wire [7:0] buf_data , output wire buf_pre_eop, output reg buf_qos ); reg ram_wen ; wire [9:0] ram_waddr; reg [8:0] ram_wdata; wire ram_ren ; wire [9:0] ram_raddr; wire [8:0] ram_rdata; reg [9:0] h_rptr ; reg [9:0] l_rptr ; reg [9:0] h_wptr ; reg [9:0] l_wptr ; reg [9:0] l_jptr ; reg l_jptr_vld; reg lf_wen ; reg [10:0] lf_wdata; wire lf_rvld ; wire lf_ren ; wire [10:0] lf_rdata; reg hf_wen ; reg [10:0] hf_wdata; wire hf_rvld ; wire hf_ren ; wire [10:0] hf_rdata; reg rx_qos_sel; wire tx_qos_sel; reg tx_busy; reg fil_pre_eop_d1; reg fil_pre_eop_d2; assign buf_vld = lf_rvld | hf_rvld; assign buf_pre_eop = ram_rdata[8]; assign buf_data = ram_rdata[7:0]; assign ram_waddr = rx_qos_sel ? h_wptr : l_wptr; assign ram_raddr = tx_qos_sel ? h_rptr : l_rptr; assign ram_ren = arb_en | tx_busy; assign tx_qos_sel = hf_rvld; always @(posedge clk or negedge rst_n) begin if(!rst_n) begin fil_pre_eop_d1 <= 1'b0; fil_pre_eop_d2 <= 1'b0; end else begin fil_pre_eop_d1 <= fil_pre_eop; fil_pre_eop_d2 <= fil_pre_eop_d1; end end always @(posedge clk or negedge rst_n) begin if(!rst_n) begin ram_wen <= 1'b0; end else begin if(fil_en) begin ram_wen <= 1'b1; end else if(fil_pre_eop_d2) begin ram_wen <= 1'b0; end end end always @(posedge clk or negedge rst_n) begin if(!rst_n) begin rx_qos_sel <= 1'b0; end else begin if(fil_en) begin rx_qos_sel <= fil_qos; end end end always @(posedge clk or negedge rst_n) begin if(!rst_n) begin h_wptr <= 10'h3FF; end else begin if(rx_qos_sel && ram_wen) begin if(h_wptr == l_wptr) begin h_wptr <= 10'h3FF; end else begin h_wptr <= h_wptr - 10'b1; end end end end always @(posedge clk or negedge rst_n) begin if(!rst_n) begin l_wptr <= 10'h0; end else begin if(!rx_qos_sel && ram_wen) begin if(l_wptr == h_wptr) begin l_wptr <= 10'h0; end else begin l_wptr <= l_wptr + 10'b1; end end end end always @(posedge clk or negedge rst_n) begin if(!rst_n) begin l_jptr <= 10'h0; l_jptr_vld <= 1'b0; end else begin if(ram_wen && (l_wptr == h_wptr)) begin l_jptr_vld <= 1'b1; if(rx_qos_sel) begin l_jptr <= l_wptr - 10'b1; end else begin l_jptr <= l_wptr; end end end end always @(posedge clk or negedge rst_n) begin if(!rst_n) begin rx_qos_sel <= 1'b0; end else begin if(fil_en) begin rx_qos_sel <= fil_qos; end end end always @(posedge clk or negedge rst_n) begin if(!rst_n) begin hf_wen <= 1'b0; end else begin hf_wen <= fil_pre_eop_d2 && rx_qos_sel; end end always @(posedge clk or negedge rst_n) begin if(!rst_n) begin lf_wen <= 1'b0; end else begin lf_wen <= fil_pre_eop_d2 && !rx_qos_sel; end end always @(posedge clk or negedge rst_n) begin if(!rst_n) begin hf_wdata <= 3'b0; lf_wdata <= 3'b0; end else begin if(fil_en) begin if(fil_qos) begin hf_wdata <= fil_id; end else begin lf_wdata <= fil_id; end end end end always @(posedge clk or negedge rst_n) begin if(!rst_n) begin ram_wdata <= 9'b0; end else begin ram_wdata <= fil_data; end end //pack out always @(posedge clk or negedge rst_n) begin if(!rst_n) begin tx_busy <= 1'b0; end else begin if(arb_en) begin tx_busy <= 1'b1; end else if(buf_pre_eop) begin tx_busy <= 1'b0; end end end always @(posedge clk or negedge rst_n) begin if(!rst_n) begin h_rptr <= 10'h3FF; end else begin if(tx_qos_sel && ram_ren) begin if(l_jptr_vld) begin if(h_rptr == l_jptr + 10'b1) begin h_rptr <= 10'h3FF; end end else begin h_rptr <= h_rptr - 10'b1; end end end end always @(posedge clk or negedge rst_n) begin if(!rst_n) begin l_rptr <= 10'h0; end else begin if(!tx_qos_sel && ram_ren) begin if(l_jptr_vld) begin if(l_rptr == l_jptr) begin l_rptr <= 10'h0; end end else begin l_rptr <= l_rptr + 10'b1; end end end end always @(posedge clk or negedge rst_n) begin if(!rst_n) begin buf_id <= 3'b0; end else begin if(arb_en) begin if(tx_qos_sel) begin buf_id <= hf_rdata; end else begin buf_id <= lf_rdata; end end end end always @(posedge clk or negedge rst_n) begin if(!rst_n) begin buf_qos <= 1'b0; end else begin if(arb_en) begin buf_qos <= tx_qos_sel; end end end RF_MEM #(10,1024,9,1,1) MEM_1024D_9W ( .clka (clk ), .clkb (clk ), .rsta_n (rst_n ), .rstb_n (rst_n ), .wr_addr(ram_waddr), .wr_data(ram_wdata), .wr_en (ram_wen ), .rd_en (ram_ren ), .rd_addr(ram_raddr), .rd_data(ram_rdata) ); SYNC_ZL_REG_FIFO #(7,3,0,0,0,0,0,0,128) HF_128D ( .clk (clk ), .rst_n (rst_n ), .fifo_clr (1'b0 ), .fifo_wr (hf_wen ), .ff_wdata (hf_wdata), .ff_afull_th(7'h7F ), .fifo_full ( ), .fifo_afull ( ), .fifo_rd (hf_ren ), .fifo_cnt ( ), .fifo_rdata (hf_rdata), .fifo_rvld (hf_rvld ), .fifo_of ( ), .fifo_uf ( ) ); SYNC_ZL_REG_FIFO #(7,3,0,0,0,0,0,0,128) LF_128D ( .clk (clk ), .rst_n (rst_n ), .fifo_clr (1'b0 ), .fifo_wr (lf_wen ), .ff_wdata (lf_wdata), .ff_afull_th(7'h7F ), .fifo_full ( ), .fifo_afull ( ), .fifo_rd (lf_ren ), .fifo_cnt ( ), .fifo_rdata (lf_rdata), .fifo_rvld (lf_rvld ), .fifo_of ( ), .fifo_uf ( ) ); endmodule
07-23
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值