zoukankan      html  css  js  c++  java
  • [XJOI]noip40 T2统计方案

    统计方案

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

    输入格式:

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

    输出格式:

    一个数,方案数模1000000007。

    样例输入:

    2 7 2

    1 2

    样例输出:

    2

    数据范围:

    对于30%的数据,n ≤ 16
    另有30%的数据,p ≤ 10000
    对于100%的数据,n ≤ 32, p ≤ 10^9, c ≤ 10^9, a[i] < p, p是质数
     
    解题思路:
    看到这种n <=32的数据范围,其实很多大佬都可以猜到这是中途相遇法
    ***如果知道这个的可以跳过下面这段介绍
    中途相遇法:事实上就是进行两次dfs,在第一次dfs时记录下搜索到的结果,
    一般用map或者hash,然后第二次是在dfs结束时根据上一次的结果,记录答案
    ***然后是对于这道题的介绍
    你先dfs前(n/2)个数,选或不选,结束时记录这些数的乘积a,我是用map来记录的
    然后在dfs后(n/2)个数,同样是选或不选,结束时得到这些数的乘积为b
    因为a*b%p=c,所以我们可以用(c/b)在%p意义下的逆元就是a的值
    最后再返回到原来的map里面找
    如果没看懂,可以借助程序在思考一下
    ***注意:(1)因为不能不取,所以在c=1的时候,答案要减一
    (2)c有可能大于等于p,这种情况直接输出0
    %:pragma GCC optimize(2)
    #include<bits/stdc++.h>
    #define int long long
    #define czx 1000000007
    using namespace std;
    int ans=0,a[50],n,p,c,m;
    map <int,int> mp;
    int pow(int a){
        int res=1,b=p-2;
        while (b){
            if (b&1) res=(res*a)%p; b/=2; a=(a*a)%p;
        }
        return res;
    }
    inline void dfs(int x,int s){
        if (x==m+1){
            mp[s]++; return;
        }
        dfs(x+1,s); dfs(x+1,1ll*s*a[x]%p);
    }
    inline void dfs1(int x,int s){
        if (x==n+1){
            int a=c*pow(s)%p;
            ans=(ans+mp[a])%czx; return;
        }
        dfs1(x+1,s); dfs1(x+1,1ll*s*a[x]%p);
    }
    main(){
        scanf("%lld%lld%lld",&n,&p,&c);
        if (c>=p){
            puts("0"); return 0;
        }
        for (int i=1;i<=n;++i)
            scanf("%lld",&a[i]);
        m=n/2; dfs(1,1); dfs1(m+1,1);
        if (c==1) ans--; printf("%lld",ans);
    }
    View Code

    最后再给上几道中途相遇法的题目

  • 相关阅读:
    判断arm立即数是否合法的小程序
    一个操作系统的实现:关于ALIGN的若干解释
    一个郁闷的C语言小问题
    test
    浮点数的比较
    一个操作系统的实现:Descriptor 3详解
    一个操作系统的实现:关于CPL、RPL、DPL
    C99可变长数组VLA详解
    SVProgressHUD 用法
    IOS CALayer 详解
  • 原文地址:https://www.cnblogs.com/logic-yzf/p/7576308.html
Copyright © 2011-2022 走看看