zoukankan      html  css  js  c++  java
  • [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
    ":"No
    ");
        }
        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;
    }
    

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

  • 相关阅读:
    COGS 14. [网络流24题] 搭配飞行员
    洛谷 P3376 【模板】网络最大流
    洛谷 P2936 [USACO09JAN]全流Total Flow
    codevs 2038 香甜的黄油 USACO
    codevs 1993 草地排水 USACO
    Openjudge 2.5 6264:走出迷宫
    洛谷 P1744 采购特价商品
    HDU
    中国剩余定理
    bzoj2157: 旅游
  • 原文地址:https://www.cnblogs.com/zi-nai-boboyang/p/11437190.html
Copyright © 2011-2022 走看看