[HAOI2015]数组游戏

Posted zi-nai-boboyang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[HAOI2015]数组游戏相关的知识,希望对你有一定的参考价值。

emmm这道题讲真是一道动态规划的题目,然而这道题你打暴力也有70分,但是如果你dp学得还不错的话这道题目的代码实现其实并不难,甚至说,比暴力还容易些。

本题提供两种写法:

暴力做法:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#define LL long long
#define inf 0x3f3f3f3f
#define maxn 100005
using namespace std;
int gi()

    int res=0,s=1; char ch;
    for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
    if(ch=='-') s=-1,ch=getchar();
    for(;ch>='0'&&ch<='9';ch=getchar()) res=res*10+ch-48;
    return res*s;

int n,cnt,mk[100];
int lef[100005],rig[100005],sg[100005],SG[100005];
int ask(int x) 
    if(n/x<=maxn) return sg[n/x];
    else return SG[n/(n/x)];

void ins(int x,int v) 
    if(n/x<=maxn) sg[n/x]=v;
    else SG[n/(n/x)]=v;

int work(int x) 
    memset(mk,0,sizeof(mk)); mk[0]=1;
    int m=n/x,sum=0,val;
    for(int i=2,pos=1;i<=m;i=pos+1) 
    pos=m/(m/i),val=ask(x*pos);
    mk[sum^val]=1;
    if((pos-i+1)&1) sum^=val;
    
    for(int i=0;;++i) if(!mk[i]) return i;

int main()

    n=gi();
    for(int i=1,pos=0;i<=n;i=pos+1)
    pos=n/(n/i),lef[++cnt]=i,rig[cnt]=pos;
    for(int i=cnt;i;--i)
    ins(rig[i],work(rig[i]));
    for(int k=gi();k;--k) 
    int num=gi(),res=0;
    for(int x;num;--num)
        x=gi(),res^=ask(x);
    printf("%s",res?"Yes\n":"No\n");
    
    return 0;

然而暴力只能过样例,打表才能出奇迹,咳咳,下面是正经做法:

正常做法:

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn=500005;
int n,Q,ans,b[maxn],c[2][maxn],vis[maxn],clk,sqrt_n;
inline int getSG(int x)
    x=n/(n/x);
    if(x<=sqrt_n) return c[0][x]; else return c[1][n/x];

void Solve()
    for(int i=1;i<=n;i=n/(n/i)+1) b[++b[0]]=n/(n/i);
    for(int i=b[0];i>=1;i--)
        int x=b[i],now=0; clk++; vis[0]=clk; 
        for(int j=x+x;j<=n;)
            int t=(n/(n/j))/x*x, cnt=(t-j)/x+1;
            vis[now^getSG(j)]=clk;
            if(cnt&1) now^=getSG(j);
            j=t+x;
        
        int res=0; while(vis[res]==clk) res++;
        if(x<=sqrt_n) c[0][x]=res; else c[1][n/x]=res;
    

int main()
    scanf("%d",&n); sqrt_n=sqrt(n)+1;
    Solve();
    scanf("%d",&Q);
    while(Q--)
        int t,x; scanf("%d",&t); ans=0;
        while(t--) scanf("%d",&x), ans^=getSG(x);
        if(ans) puts("Yes"); else puts("No");
    
    return 0;

怎么样,是不是正常写法比暴力还容易些?

以上是关于[HAOI2015]数组游戏的主要内容,如果未能解决你的问题,请参考以下文章

[HAOI2015]数组游戏

[HAOI2015] 数组游戏 - 博弈论,SG函数

[HAOI2016]找相同字符(后缀数组+单调栈)

字符串(后缀数组):HAOI2016 找相同子串

HAOI2015PG图

BZOJ4566 [Haoi2016]找相同字符 后缀数组