zoukankan      html  css  js  c++  java
  • 校长的密码

    前言

    当拿到这道题只想打暴力的时候,我就已经输了。

    题目

    题目大意

    校长 ( t DD(XYX)) 在知乎上开启了隐私保护!为了得知校长的最新动态并跟随他的脚步,他忠诚的追随者们需要破解他的隐私密码。

    校长的隐私密码由长达 (N) 位的数码组成,每一位的数码范围为 ([1,K])

    校长的密码并非完全无迹可寻,根据校长的日常用语以及行为准则,他的追随者们得到了 (M) 个信息,每个信息有两个整数 (a_i,b_i) ,表示数码 (a_i) 不会出现在 (b_i) 之前。

    为了估算破解密码的时间花费,你需要计算出一共有多少种不同的密码。

    同时它的追随者们对每一种密码视为十进制数的算术和很感兴趣,认为这是校长神通广大的原力,所以你也需要计算出来,而且不允许有任何作假!(不取模)

    (1le Nle 500;0le Mle 100;Kle 9.)

    嘿,小声点,小心被校长发现了!还有,动作快点,(1s) 是极限了!

    样例

    样例输入1

    4 4 3
    1 1
    1 2
    2 2
    3 1
    

    样例输出1

    7
    19020
    

    讲解

    这道题 (M=0) 的数据有 (50pts),加上 (Nle 6)(20pts) 就有 (70pts),所以完全没打算想正解,佛了。

    考试结束后一琢磨,这不是状压+高精板题吗?!

    从高位向低位DP可以避免高精乘高精。

    时间复杂度 (O(2^KKNC)),其中 (C) 是高精度复杂度。

    代码

    由于OJ太烂而需要大力卡常还加了Ofast的代码
    //12252024832524
    #pragma GCC optimize("Ofast")
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define TT template<typename T>
    using namespace std;
      
    typedef long long LL;
    const int MAXN = 100005;
    int n,m,k;
      
    LL Read()
    {
        LL x = 0,f = 1; char c = getchar();
        while(c > '9' || c < '0'){if(c == '-') f = -1;c = getchar();}
        while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();}
        return x * f;
    }
    TT void Put1(T x)
    {
        if(x > 9) Put1(x/10);
        putchar(x%10^48);
    }
    TT void Put(T x,char c = -1)
    {
        if(x < 0) putchar('-'),x = -x;
        Put1(x); if(c >= 0) putchar(c);
    }
    TT T Max(T x,T y){return x > y ? x : y;}
    TT T Min(T x,T y){return x < y ? x : y;}
    TT T Min(T x){return x < 0 ? -x : x;}
      
    const LL N = 100000000000000000ll;
    struct BigNum
    {
        bool hv;
        int len;
        LL a[145];
          
        BigNum(){memset(a,0,sizeof(a));}
          
        void init(LL x)
        {
            for(int i = 0;i <= len;++ i) a[i] = 0;
            len = -1; hv = 1;
            do
            {
                a[++len] = x%N;
                x/=N;
            }while(x);
        }
          
        BigNum operator + (const BigNum &C)const
        {
            BigNum ret; ret.len = Max(len,C.len); ret.hv = 1;
            LL jw = 0;
            for(int i = 0;i <= ret.len;++ i)
            {
                ret.a[i] = a[i]+C.a[i]+jw;
                jw = ret.a[i] / N; 
                ret.a[i] %= N;
            }
            while(jw) ret.a[++ret.len] = jw%N,jw/=N;
            return ret;
        }
          
        BigNum operator * (const LL x)const
        {
            BigNum ret; LL jw = 0; ret.len = len; ret.hv = 1;
            for(int i = 0;i <= len;++ i)
            {
                ret.a[i] = a[i]*x+jw;
                jw = ret.a[i] / N;
                ret.a[i] %= N;
            }
            while(jw) ret.a[++ret.len] = jw%N,jw/=N;
            return ret;
        }
         
        void operator += (const BigNum &C)
        {
            LL jw = 0; len = Max(len,C.len); hv = 1;
            for(int i = 0;i <= len;++ i)
            {
                if(!jw && i > C.len) break;
                a[i] = a[i]+C.a[i]+jw;
                jw = a[i]/N;
                a[i] %= N;
            }
            while(jw) a[++len] = jw%N,jw/=N;
        }
          
        void print()
        {
            if(len < 0) return; Put(a[len]);
            for(int i = len-1;i >= 0;-- i) printf("%017lld",a[i]);
            putchar('
    ');
        }
    };
    int fk[10][10];
    BigNum cnt[2][1<<9],dp[2][1<<9];
    bool can[9][1<<9];
    int lowbit(int x){return x & -x;}
      
    int main()
    {
        freopen("hacker2.in","r",stdin);
        freopen("hacker2.out","w",stdout);
        n = Read(); m = Read(); k = Read(); 
        for(int i = 1;i <= m;++ i)
        {
            int u = Read(),v = Read();
            fk[u-1][v-1] = 1;
        }
        int sx = (1<<k) - 1;
        for(int S = 0;S <= sx;++ S)
            for(int i = 0;i < k;++ i)
            {
                can[i][S] = 1;
                for(int j = 0;j < k;++ j)
                    if((S >> j & 1) && fk[j][i])
                        can[i][S] = 0;
            }
        dp[0][0].init(0); cnt[0][0].init(1);
        for(int i = 1;i <= n;++ i)
        {
            bool now = i&1;
            for(int S = 0;S <= sx;++ S) dp[now][S].init(0),cnt[now][S].init(0),dp[now][S].hv = cnt[now][S].hv = 0;
            for(int S = 0;S <= sx;++ S)
            {
            	dp[now^1][S]=dp[now^1][S]*10;
    			for(int j = 0;j < k;++ j)
                {
                    if(!can[j][S] || !cnt[now^1][S].hv) continue;
                    dp[now][S|(1<<j)] += dp[now^1][S];
    				dp[now][S|(1<<j)] += cnt[now^1][S]*(j+1);
                    cnt[now][S|(1<<j)] += cnt[now^1][S];
                }
            }
        }
        BigNum ans1,ans2; ans1.init(0); ans2.init(0);
        for(int S = 0;S <= sx;++ S) ans1 += cnt[n&1][S],ans2 += dp[n&1][S];
        ans1.print(); ans2.print(); 
        return 0;
    }
    
  • 相关阅读:
    【计算几何】多边形交集
    【计算几何】点在多边形内部
    【计算几何】线段相交
    【计算几何】多边形点集排序
    【JavaScript学习】JavaScript对象创建
    【CUDA学习】内核程序调试
    【CUDA学习】共享存储器
    【CUDA学习】全局存储器
    Charles是Mac的Fiddler抓包工具
    Charles是mac的iddler抓包工具
  • 原文地址:https://www.cnblogs.com/PPLPPL/p/15371996.html
Copyright © 2011-2022 走看看