zoukankan      html  css  js  c++  java
  • 概率加密

    众所周知,小葱同学擅长计算,尤其擅长计算组合数,但这个题和组合数没什么关系。


    小葱同学为了庆祝题目套数突破150,小葱同学自创了概率加密算法。现在小葱同学有一个N位的密码,密码的每一位都是1 − N中的一个数。现在小葱自创的随机加密算法会给你N个数xi,代表每次进行加密的时候,所有为i的为都会变成xi,而当N位的密码全部变成和它一开始N位一样之后,小葱同学的加密算法也就停止了。所以,给定这个密码,然后求需要进行多少次加密是一个非常困难的问题。为了简化这个问题,现在小葱假定我们并不知道输入的密码,输入的密码是一个随机的密码,即总共MN种可能性每种可能性的概率为M-N 。小葱同学想要知道,在这种情况下,这个随机密码期望需要多少次能够完成加密操作。

    【输入格式】
    一行两个数N,M。
    接下来一行M个数代表Xi
    【输出格式】
    输出一行一个整数,代表期望的次数乘以MN 模109 + 7的结果。
    【样例输入 1】
    2 2
    1 2
    【样例输出 1】
    4
    【样例输入 2】
    2 2
    2 1
    【样例输出 2】
    8
    【数据规模与约定】
    对于40%的数据,N,M ≤ 5。
    70%的数据,N,M ≤ 20。
    对于100%的数据,1 ≤ N,M ≤ 100,1 ≤ xi ≤ M,保证所有xi互不相同。

    对于单独的一个数i,经过k次重新变为i,保证所有的k乘积小于100。

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #include <map>
    #define INF 1e9 + 7
    #define MAXN 2000
    #define int long long
    #define MOD 1000000007
    
    using namespace std;
    
    inline int read()
    {
        int 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 f * x;
    }
    inline int max(int a, int b){return a > b ? a : b;}
    inline int min(int a, int b){return a < b ? a : b;} 
    
    int n, m, x[MAXN], num[MAXN];
    
    inline int check(int s)
    {
        int sum = 1, k = s;
        k = x[k];
        while (k != s){sum++; k = x[k];}
        return sum;
    }
    
    inline int gcd(int x, int y){return y == 0 ? x : gcd(y, x % y);}
    inline int lcm(int x, int y){return x * y / gcd(x, y);}
    
    int f[105][105][MAXN], vis[MAXN], cnt;//设f[i][j][k]为当前为i位,i位上为j这个数,与前面的数的lcm为k时的方案数,vis储存有多少个lcm
    map<int, int> VIS;
    
    void find(int now, int sum)
    {
        if (now == n + 1) return;
        for (int i = 1; i <= m; i++)
        {
            int k = lcm(sum, num[i]);
            if (!VIS[k])
            {
                vis[++cnt] = k;
                VIS[k] = 1;
                find(now + 1, k);
            }
        }
    }
    
    inline int step_2()
    {
        find(1, 1);
        for (int i = 1; i <= m; i++)    f[1][i][num[i]] = 1;
    
        for (int i = 2; i <= n; i++)
            for (int j = 1; j <= m; j++)
                for (int k = 1; k <= cnt; k++)
                    for (int N = 1; N <= cnt; N++)
                        if (lcm(vis[N], num[j]) == vis[k])
                            for (int M = 1; M <= m; M++)
                                f[i][j][k] += f[i - 1][M][N], f[i][j][k] %= MOD;
        int ans = 0;
        for (int i = 1; i <= m; i++)
            for (int j = 1; j <= cnt; j++)
                ans += f[n][i][j] * vis[j], ans %= MOD;
        cout << ans << endl;
        return 0;
    }
    
    signed main()
    {
        freopen("prob.in", "r", stdin);
        freopen("prob.out", "w", stdout);
        n = read(), m = read();
        for (int i = 1; i <= m; i++) x[i] = read();
        for (int i = 1; i <= m; i++) num[i] = check(i);
    
        return step_2();
    
        return 0;
    }
    View Code
  • 相关阅读:
    Android用户界面开发(4):EditText
    Android用户界面开发(12):Dialog
    Android用户界面开发(5):单项选择
    Android用户界面开发(6):多项选择
    Android用户界面开发(2):ListView
    Android特色开发(2):语音识别
    Android用户界面开发(9):日期和时间
    Android用户界面开发(3):Toast
    Android用户界面开发(15):Gallery
    Android特色开发(1):传感器
  • 原文地址:https://www.cnblogs.com/dead-gun/p/12991193.html
Copyright © 2011-2022 走看看