zoukankan      html  css  js  c++  java
  • ExaWizards 2019 English D

    Time Limit: 2 sec / Memory Limit: 1024 MB

    Score : 600600 points

    Problem Statement

    Snuke has a blackboard and a set SS consisting of NN integers. The ii-th element in SS is SiSi.

    He wrote an integer XX on the blackboard, then performed the following operation NN times:

    • Choose one element from SS and remove it.
    • Let xx be the number written on the blackboard now, and yy be the integer removed from SS. Replace the number on the blackboard with xmodyxmody.

    There are N!N! possible orders in which the elements are removed from SS. For each of them, find the number that would be written on the blackboard after the NN operations, and compute the sum of all those N!N! numbers modulo 109+7109+7.

    Constraints

    • All values in input are integers.
    • 1N2001≤N≤200
    • 1Si,X1051≤Si,X≤105
    • SiSi are pairwise distinct.

    Input

    Input is given from Standard Input in the following format:

    NN XX
    S1S1 S2S2  SNSN
    

    Output

    Print the answer.


    Sample Input 1 Copy

    Copy
    2 19
    3 7
    

    Sample Output 1 Copy

    Copy
    3
    
    • There are two possible orders in which we remove the numbers from SS.
    • If we remove 33 and 77 in this order, the number on the blackboard changes as follows: 191119→1→1.
    • If we remove 77 and 33 in this order, the number on the blackboard changes as follows: 195219→5→2.
    • The output should be the sum of these: 33.

    Sample Input 2 Copy

    Copy
    5 82
    22 11 6 5 13
    

    Sample Output 2 Copy

    Copy
    288
    

    Sample Input 3 Copy

    Copy
    10 100000
    50000 50001 50002 50003 50004 50005 50006 50007 50008 50009
    

    Sample Output 3 Copy

    Copy
    279669259
    
    • Be sure to compute the sum modulo 109+7109+7.

    题意:

    给定一个数x和一个含有n个数的数组。

    将数组排成任意顺序(即一共有N!种顺序组合),然后扫一遍数组,x对a[i] 取模,余数代替x,然后对下一个数进行同样的操作。

    直到扫完整个数组。最后得到的数是num

    然后把所有顺序组合得到的num全加起来就是ans,需要对1e9+7取模。

    思路:

    通过分析我们可以知道,

    当数组的一个数a[i]前面有一个数a[x],并且a[x] 比 a[i] 小。那么我们分析上面的取余操作可以知道a[i]其实对答案没有任何影响。

    因为在对a[i]取余之前的数值x,已经比a[i]小了,因为对a[x]取余过了,一个小数对大数取余,没有改变的。

    那么我们对数组从大到小排序后,

    定义dp[i][j] 表示,排列了前i个数后,当前值x为j的所有情况数。

    转移有两种,

    如果a[i] 数放在 i位置,

    那么我们知道他对i位置 j%a[ i ] 的贡献是上一个位置i-1的j的数量。

    如果a[i] 不放在这个位置。

    它放在后面的n-i的任意位置都可以,而且对当前位置i的j即dp[i][j]的贡献就是dp[i-1][j] ,因为这一位的 a[i] 没有影响。

    细节见代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <map>
    #include <set>
    #include <vector>
    #include <iomanip>
    #define ALL(x) (x).begin(), (x).end()
    #define rt return
    #define dll(x) scanf("%I64d",&x)
    #define xll(x) printf("%I64d
    ",x)
    #define sz(a) int(a.size())
    #define all(a) a.begin(), a.end()
    #define rep(i,x,n) for(int i=x;i<n;i++)
    #define repd(i,x,n) for(int i=x;i<=n;i++)
    #define pii pair<int,int>
    #define pll pair<long long ,long long>
    #define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
    #define MS0(X) memset((X), 0, sizeof((X)))
    #define MSC0(X) memset((X), '', sizeof((X)))
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    #define eps 1e-6
    #define gg(x) getInt(&x)
    #define db(x) cout<<"== [ "<<x<<" ] =="<<endl;
    using namespace std;
    typedef long long ll;
    ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
    ll powmod(ll a,ll b,ll MOD){ll ans=1;while(b){if(b%2)ans=ans*a%MOD;a=a*a%MOD;b/=2;}return ans;}
    inline void getInt(int* p);
    const int maxn=1000010;
    const int inf=0x3f3f3f3f;
    /*** TEMPLATE CODE * * STARTS HERE ***/
    int a[maxn];
    int n;
    int x;
    ll dp[202][100010];
    const ll mod=1e9+7;
    int main()
    {
        //freopen("D:\common_text\code_stream\in.txt","r",stdin);
        //freopen("D:\common_text\code_stream\out.txt","w",stdout);
        gbtb;
        cin>>n>>x;
        repd(i,1,n)
        {
            cin>>a[i];
        }
        sort(a+1,a+1+n,[&](int x,int y){return x>y;});
        dp[0][x]=1;
        repd(i,1,n)
        {
            repd(j,0,x)
            {
                dp[i][j%a[i]]+=dp[i-1][j];
                dp[i][j%a[i]]=(dp[i][j%a[i]]+mod)%mod;
                dp[i][j]+=dp[i-1][j]*(n-i)%mod;
                dp[i][j]=(dp[i][j]+mod)%mod;
            }
        }
        ll ans=0ll;
        repd(i,0,x)
        {
            ans+=(dp[n][i]*i)%mod;
            ans=(ans+mod)%mod;
        }
        cout<<ans<<endl;
    
    
    
        return 0;
    }
    
    inline void getInt(int* p) {
        char ch;
        do {
            ch = getchar();
        } while (ch == ' ' || ch == '
    ');
        if (ch == '-') {
            *p = -(getchar() - '0');
            while ((ch = getchar()) >= '0' && ch <= '9') {
                *p = *p * 10 - ch + '0';
            }
        }
        else {
            *p = ch - '0';
            while ((ch = getchar()) >= '0' && ch <= '9') {
                *p = *p * 10 + ch - '0';
            }
        }
    }

    本博客为本人原创,如需转载,请必须声明博客的源地址。 本人博客地址为:www.cnblogs.com/qieqiemin/ 希望所写的文章对您有帮助。
  • 相关阅读:
    IIS 添加二级应用程序
    VS中发布并调试IIS程序
    未启用当前数据库的 SQL Server Service Broker,因此查询通知不受支持。如果希望使用通知,请为此数据库启用 Service Broker
    Flash基础开发习惯指要
    2012云计算扫盲
    flash问题集锦(新手必看)
    Flash常用ActionScript控制语句基本用法祥解
    通过offset值的设置使html元素对齐
    不用float也可以让div横向显示
    QQ空间里写的开发心得
  • 原文地址:https://www.cnblogs.com/qieqiemin/p/10726803.html
Copyright © 2011-2022 走看看