zoukankan      html  css  js  c++  java
  • SZOJ 134 圆环炸裂

    题目描述
    现在有一个圈,圈上有n个点,每个点之间的距离是m,你从起点出发,带着t个跳跃模组进行巡逻,每次使用一次跳跃模组i,跳跃的距离是ai
    一个合法的巡逻路线理应从一个点开始,经过若干次跳跃之后(顺时针或者逆时针),在某个点停下来(不一定要用掉所有的跳跃模组)

    或者更正式地说∑ai∗xi≡0(mod m), 其中xi可以是±1,0, 但是不能全为0
    一个邪恶的破坏者想要让你无法完成合法的跳跃,现在,你想要知道有多少种可能的破坏(也就是拿掉若干个跳跃模组)方案,答案也许很大,请将答案对10^9+7取余

    输入格式
    第一行输入三个整数n, m, t
    第二行t个整数,表示每个跳跃模组的跳跃距离ai
    输出格式
    输出使你无法进行巡逻的破坏方案总数

    样例输入
    7 6 5
    5 4 12 6 5
    样例输出
    6
    数据规模
    对于10%的数据,t≤10
    对于30%的数据,m≤70
    对于60%的数据,m≤100
    对于100%的数据,2≤n≤1000,1≤m≤120,1≤t≤10000,每个跳跃的距离不超过10^9

    一道原本坐等有人接单然后听题解结果石沉大海的题目,只好麻烦把学长问到吐血了

    其实题目就是 ∑ai∗xi≡0(mod m), 其中xi可以是±1,0, 但是不能全为0,让其不成立,如果我们真的去破坏的话。。。我也不知道怎么做了,暴力吧

    所以我们反过来直接枚举对于 “∑ai∗xi≡0(mod m), 其中xi可以是±1,0, 但是不能全为0” 来说非法的情况

    由于是∑ai∗xi≡0(mod m),在mod m的意义下,我们将ai做如下处理,ai=min(ai%m,(m-ai)%m),即在顺时针和逆时针走中取一个最小值,为什么呢,因为我们要压ai的范围,经过这么处理以后,ai的范围就在60以内了

    然后我们进行拼凑,拿着目前的ai,只要它mod m 不为0,那么都是对答案有贡献的,将手上所有的ai都用上(即为破坏原题目的合法性)。

    这题ai的范围有60,所以我们直接枚举ai就好了,对于目前的长度x,其对应有一个计数器S,二进制下S的每一位表示此时长度是否已经被凑出来过,用0与1表示,那么对于每个长度,首先只要这个长度是合法的,我们就可以将他们都用上,这有一种贡献,当这个长度是我们处理过的ai时,首先我们先确定它是否合法,即看S中有没有已经凑出过的长度,如果有,那么顺时针一下逆时针一下就不能破坏了,这种就对答案没有贡献了,所以在保证是合法的情况下,我们对于每个原有的长度加上ai或者减去ai,咋办呢?——循环位移,左移移右移移就好了,啊,什么是循环位移

    所以这道题就是这样啦。。。

    其实代码也不会很长。。。

    #include<iostream>
    #include<cstdlib>
    #include<cstdio>
    #include<algorithm>
    #define ull unsigned long long
    #define mod 1000000007LL
    using namespace std;
    int n,m,t,cnt[71],REV[1<<16];
    ull fullnum;
    inline int fix(int x){
        while(x<=0)
            x+=m;
        while(x>=m)
            x-=m;
        return x;
    }
    inline int rev16bit(int x){
        int ret=0;
        for(int i=1;i<=16;i++)
            ret=2*ret+(x&1),x/=2;
        return ret;
    }
    inline ull reverse(ull  x)
    {
        ull A = (x>>48) & ((1LL << 16)-1);
        ull B = (x>>32) & ((1LL << 16)-1);
        ull C = (x>>16) & ((1LL << 16)-1);
        ull D = (x) & ((1LL << 16)-1);
        A = REV[A], B = REV[B], C = REV[C], D = REV[D];
        return ((D<<48)|(C<<32)|(B<<16)|A);
    }
    inline ull xh(ull curMask, int shift)
    {
        ull ret = curMask;
        ull rev = reverse(curMask) >> (63 - m/2);
        ret |= (curMask << shift);
        ret |= (curMask >> shift);
        ret |= (rev >> (m/2 - shift));
        ret |= (rev << (m/2 + (m&1) - shift));
        return ret & fullnum;
    }
    inline long long dfs(int x,long long S){
        if(x>m/2+1)
            return 1;
        long long ret=0;
        ret+=dfs(x+1,S);
        if(cnt[x]>0)
            if((S&(1LL<<x))==0)
                ret+=cnt[x]*dfs(x+1,xh(S,x));
        ret=ret%mod;
        return ret;
    }
    inline void Jimmy(){
        scanf("%d%d%d",&n,&m,&t);
        for(int i=0;i<(1<<16);i++)
            REV[i]=rev16bit(i);
        fullnum=(1LL<<(1+m/2))-1;
        for(int i=1;i<=t;i++){
            long long c;
            scanf("%lld",&c);
            cnt[min(fix(c%m),fix(-(c%m)))]++;
        }
        printf("%lld
    ",dfs(1,1)%mod);
    }
    int main(){
        Jimmy();
        return 0;
    } 
    View Code
  • 相关阅读:
    Unity3d Platformer Pro 2D游戏开发框架使用教程
    程序员如何学习一门新的编程语言
    走进函数式编程
    1001. Exponentiation高精度运算总结
    Kindle PaperWhite3 越狱和PDF插件的安装
    Unity3d中的PlayerPrefs游戏存档API的扩展
    程序员学习路线和学习书单
    1000. A+B Problem
    Mac端SVN工具CornerStone详解
    Unity3d粒子系统详解
  • 原文地址:https://www.cnblogs.com/JimmyC/p/6528673.html
Copyright © 2011-2022 走看看