zoukankan      html  css  js  c++  java
  • XJOI 夏令营501-511测试11 统计方案

    小B写了一个程序,随机生成了n个正整数,分别是a[1]..a[n],他取出了其中一些数,并把它们乘起来之后模p,得到了余数c。但是没过多久,小B就忘记他选了哪些数,他想把所有可能的取数方案都找出来。你能帮他计算一下一共有多少种取数方案吗?请把最后的方案数模1000000007后输出。
    小B记得他至少取了一个数。

    输入格式:

    第一行三个正整数n,p,c,含义如题目所述。
    接下来一行有n个正整数,表示生成的n个随机数。

    输出格式:

    一个数,方案数模1000000007。

    样例输入:

    2 7 2
    1 2 4

    样例输出:

    2

    数据范围:

    对于30%的数据,n≤16
    另有30%的数据,p≤10000
    对于100%的数据,n≤32, p≤10^9, c≤10^9, a[i]<p, p是质数

    时间限制:

    1 sec

    空间限制:

    128MB

    折半搜索+逆元

    因为n只有32的范围

    所以考虑折半搜索,将前$frac{n}{2}$和后$frac{n}{2}$个元素的所有乘积处理出来

    然后将这两组之间的元素进行匹配

    对于一组中的乘积$a$,那么需要在另一组中找到$b$,满足$a*b equiv c$

    那么可以发现$b$为$a$的逆元$k$再乘上$c$,因为$p$是质数,那么$k$可以用费马小定理解决

    即$b=a^{p-2}*c$,在$b$的数组中二分查找即可

    还有这道题有个坑点

    1.如果$cgeq p$答案即为0

    #include <bits/stdc++.h>
    #define mod 1000000007
    #define ll long long
    using namespace std;
    ll n,p,c,a[1000],tot,ans;
    vector <ll> s;
    vector <pair<ll,ll> > t;
    ll m_pow(ll a,ll b)//快速幂,求逆元
    {
        ll ans=1;
        while (b)
        {
            if (b&1)
              ans=(ans*a)%p;
            b>>=1;
            a=(a*a)%p;
        }
        return ans;
    }
    void dfs1(ll x,ll l,ll r,ll sum)//用dfs求出每一个乘积
    {
        if (x==r+1)
        {
            ll ne;
            ne=(m_pow(sum,p-2)*c)%p;//将每一乘积需要的答案压入数组
            s.push_back(ne);
            return;
        }
        dfs1(x+1,l,r,sum);
        dfs1(x+1,l,r,(sum*a[x])%p);
    }
    void dfs2(ll x,ll l,ll r,ll sum)
    {
        if (x==r+1)
        {
            vector <pair<ll,ll> > :: iterator it;
            it=lower_bound(t.begin(),t.end(),make_pair(sum,(ll)0));//进行匹配
            if ((*it).first==sum)
              ans=(ans+(*it).second)%mod;
            return;
        }
        dfs2(x+1,l,r,sum);
        dfs2(x+1,l,r,(sum*a[x])%p);
    }
    int main()
    {
        scanf("%lld%lld%lld",&n,&p,&c);
        for (ll i=1;i<=n;i++)
          scanf("%lld",&a[i]);
        if (c>=p)
        {
            printf("0
    ");
            return 0;
        }
        for (ll i=1;i<=n;i++)
          a[i]%=p;
        dfs1(1,1,n/2,1);
        sort(s.begin(),s.end());
        ll kind=s[0],w=1;
        for (ll i=1;i<(ll)s.size();i++)
        {
            if (s[i]==kind)
              w++;
            else
            {
                t.push_back(make_pair(kind,w));
                w=1;
                kind=s[i];
            }
        }
        t.push_back(make_pair(kind,w));
        tot=0;
        dfs2(n/2+1,n/2+1,n,1);
        if (c==1)
          ans=(ans-1)%mod;
        printf("%lld
    ",ans%mod);
    }
  • 相关阅读:
    单页应用 SPA(Sigle Page Aolication)
    初学数据库
    AJAX与跨域
    面向对象
    event、Dom
    HTML DOM Event 对象
    JavaScript RegExp 对象
    UNITY常用插件
    数据分析师
    VBA工作表排序转载
  • 原文地址:https://www.cnblogs.com/huangchenyan/p/11254762.html
Copyright © 2011-2022 走看看