ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[atARC144F]Arithmetic Sequence Nim

2022-07-23 07:31:34  阅读:130  来源: 互联网

标签:atARC144F return Nim int ll mid sg Arithmetic define


记$sg(n)={\rm mex}\{sg(n-x)\mid x\in X\}$,考虑如何求$sg(n)$——

将$m,a,n$均除以$\gcd(m,a)$(其中$n$向下取整),以下假设$m,a$互素

特判$a=0(m=1)$的情况,此时$sg(n)=n$,以下假设$a\in [1,m)$

用$(i,j)$表示$im+ja$,则$sg(i,j)={\rm mex}\{sg(k,j-1)\mid k\le i\}$(注意$i,j$均可为负)

显然$sg(i,j)$关于$i$单调不降,且每次至多增加$1$(单调不降的$sg(i-1,j)$的前缀${\rm mex}$)

对$j$从小到大转移,维护$\{sg(i,j)\}$并分类讨论:

1.若序列开头不为$0$,结合单调不降的性质,转移后所有元素均为$0$

2.若序列开头为$0$,结合"至多增加$1$"的性质,转移后所有元素均增加$1$

另外,每次会在序列开头加入$\lceil\frac{-(j-1)a}{m}\rceil-\lceil\frac{-ja}{m}\rceil\in [0,1]$个$0$(转移后)

在此基础上,求出$im+ja=n$的某组解$(i,j)$,并分类讨论:

1.若$(i,j-1)$不存在(即作为加入的$0,\iff n<a$),则$sg(i,j)=0$

2.若$j-1$处未在开头加入$0$,记$j_{0}$为$<j$中第一个加入$0$的位置,则$sg(i,j)=(j-j_{0})\ mod\ 2$

3.若$j-1$处在开头加入$0$,记$j_{1}$为$<j$中第一个未加入$0$的位置,$j_{0}$为$<j_{1}$中第一个加入$0$的位置

结合分析,即$sg(i,j)=\begin{cases}i-s&i-s<j-j_{1}\\ j-j_{1}-(j_{1}-j_{0})\ mod\ 2&i-s\ge j-j_{1}\end{cases}$(其中$s=\lceil\frac{-(j-1)a}{m}\rceil-1$)

关于原问题,可以直接推公式,或利用单调性二分求出对应权值区间

时间复杂度视实现而定,最优应为$o(n+\log m)$,可以通过

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 300005
 4 #define mod 998244353
 5 #define ll long long
 6 #define LL __int128
 7 int n,m,a,d,x,y,ans;
 8 ll s,A[N],sA[N],sB[N];
 9 int exgcd(int a,int b,int &x,int &y){
10     if (!b){x=1,y=0;return a;}
11     int d=exgcd(b,a%b,y,x);y-=a/b*x;return d;
12 }
13 ll get(ll j){
14     return (-j*a+(j<0 ? m-1 : 0))/m;
15 }
16 ll get0(ll j){
17     ll s=get(j);
18     return (-s*m+(s<0 ? a-1 : 0))/a;
19 }
20 ll get1(ll j){
21     ll s=get(j)+j;
22     return ((LL)(s-1)*m+(s>0 ? m-a : 1))/(m-a);
23 }
24 ll Sg(ll n){
25     if (!a)return n;
26     if (n<a)return 0;
27     ll i=(n%a)*x%a,j=(n-i*m)/a;
28     if (get(j-1)==get(j-2))return (j-get0(j-1)&1);
29     ll s=get(j-1)-1,j1=get1(j-1),j0=get0(j1-1);
30     return (i-s<j-j1 ? i-s : j-j1-(j1-j0&1));
31 }
32 ll sg(ll n){
33     m/=d,a/=d,n=Sg(n/d);
34     m*=d,a*=d;return n;
35 }
36 ll find(int i,ll s){
37     if (sB[i]<s)return 0;
38     ll l=0,r=(A[i]-a)/m;
39     while (l<r){
40         ll mid=(l+r+1>>1);
41         if (sg(A[i]-a-m*mid)>=s)l=mid;
42         else r=mid-1;
43     }
44     return (l+1)%mod;
45 }
46 int main(){
47     scanf("%d%d%d",&n,&m,&a);
48     d=exgcd(m,a,x,y);
49     for(int i=1;i<=n;i++){
50         scanf("%lld",&A[i]);
51         sA[i]=sg(A[i]),sB[i]=sg(A[i]-a),s^=sA[i];
52     }
53     for(int i=1;i<=n;i++)
54         ans=(ans+(find(i,(sA[i]^s))-find(i,(sA[i]^s)+1)+mod))%mod;
55     printf("%d\n",ans);
56     return 0;
57 } 
View Code

 

标签:atARC144F,return,Nim,int,ll,mid,sg,Arithmetic,define
来源: https://www.cnblogs.com/PYWBKTDA/p/16508448.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有