zoukankan      html  css  js  c++  java
  • luogu P4752

    给定一个数字 A ,这个 A 由 a1,a2,...,aN 相乘得到。

    给定一个数字 B ,这个 B 由 b1,b2,,bM 相乘得到。

    如果 A/B 是一个质数,请输出YES,否则输出NO

    输入输出格式

    输入格式:

    每个测试点包含多组数据,第一行读入一个整数 TT 表示数据组数,对于每组数据:

    第一行输入两个整数 N,M ,分别表示 A 由 N 个数字相乘得到, B 由 M 个数字相乘得到。

    第二行输入 N 个整数,分别表示组成 A 的 N 个数字。

    第三行输入 M 个整数,分别表示组成 B 的 M 个数字。

    保证对于一个数字,其在 {bi}中出现的次数不多于在 {ai} 中出现的次数。

     

    输出格式:

     

    对于每组数据:

    如果 A/B 是一个质数,请输出YES,否则输出NO

    在输出 YES 或 NO后输出一个换行符。

    输入输出样例

    输入样例#1: 
    2
    3 2
    5 7 7
    5 7
    4 2
    5 7 7 7
    5 7
    输出样例#1: 
    YES
    NO

    说明

    1N100000

    0MN

    1ai,bi1012

    1T10

    N100000

     吐槽两句:

    说好的难度从普及-到省选呢?普及-难度呢?最低的只有 普及+提高-的吧,然而我看着都想省选题。

    体面解读解题分析:

    题面简洁易懂,只是根据数据范围,貌似如果相乘的话long long 恐怕都盛不开。

    然而细细读题目你会发现,有句很重要的话(红色标注)

    既然是A/B,那么 集合A 与 集合B中的元素可以先提前约分啊。

    这句话说的数字在 B 中出现次数一定少于 A中的次数,那么这说明B中的数字可以在A中全部约去,那么B=1咯,所以A/B的值不就是A中所剩元素的乘积嘛。

    少年,莫着急,等我把话说完。

    A中元素的乘积难道就会小?绝对有数据会乘不开。

    所以在约分完以后,需要一个比较有意思的判断。

    你想A中元素的乘积,既然可以乘出来,那么一定就不是素数(prime).(emmm...说的在理)

    还需要加一个判断,如果A中只剩下一个元素后,那么乘积就是这个数了,则需要判断一下这个数是否为素数。

    1012大的数,用什么判断呢?

    当然是 Miller_Rabin 算法判断了,下面给出了模板。

    所以此题就解决完了。

    Miller_Rabin模板

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define ll long long
    using namespace std;
    
    ll add_mod(ll a,ll b,ll mod){    //快乘法 基于快速幂的二分思想 
        ll ans=0;                    //由于考虑到取模数很大 快速幂会溢出 
        while(b){                    //必须使用该方法 
            if(b&1)                    //我这里写的是非递归版 
                ans=(ans+a)%mod;
            a=a*2%mod;
            b>>=1;
        }
        return ans;
    }
    
    ll pow_mod(ll a,ll n,ll mod){            //快速幂 递归版 
        if(n>1){                            
            ll tmp=pow_mod(a,n>>1,mod)%mod;
            tmp=add_mod(tmp,tmp,mod);
            if(n&1) tmp=add_mod(tmp,a,mod);
            return tmp;
        }
        return a;
    }
    
    bool Miller_Rabbin(ll n,ll a){//米勒拉宾素数判断函数主体
        ll d=n-1,s=0,i;    
        while(!(d&1)){            // 先把(2^s)*d 算出来 
            d>>=1;
            s++;
        }
        ll t=pow_mod(a,d,n);    //a^d取一次余判断 
        if(t==1 || t==-1)        //一或负一则可以声明这可能是质数 
            return 1;
        for(i=0;i<s;i++){                //不是的话继续乘上s个2 
            if(t==n-1)            //(n-1)*(n-1)%n=1 这一步是优化 
                return 1;
            t=add_mod(t,t,n);    // 快乘 
        }
        return 0;
    }
    
    bool is_prime(ll n){
        ll i,tab[4]={3,4,7,11};//本来应该取[1,n]内任意整数 
        for(i=0;i<4;i++){                //但一般这几个数足以,不需要太多组测试 
            if(n==tab[i])
                return 1;        //小判断小优化~ 
            if(!n%tab[i])
                return 0;
            if(n>tab[i] && !Miller_Rabbin(n,tab[i]))
                return 0;
        }
        return 1;
    }
        
    int main(){
        ll n;
        scanf("%lld",&n);
        if(n<2) printf("No");
        else if(n==2) printf("Yes");
        else{
            if(!n%2) printf("No");
            else if(is_prime(n))
                printf("Yes");
            else printf("No");
        }
        return 0;
    }

    此题AC代码

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <queue>
    #include <map>
    using  namespace std;
    #define N int(1e6+2)
    #define M int(2e5+2)
    #define ll long long
    ll n,m,T;
    ll a[N],b,c[N],tot;
    map<ll,int> f;
    bool vis[N];
    ll sum;
    ll add_mod(ll a,ll b,ll mod)
    {
        ll ans=0;
        while(b)
        {
            if(b&1)
                ans=(ans+a)%mod;
            a=a*2%mod;
            b>>=1;
        }
        return ans;
    }
    
    ll pow_mod(ll a,ll n,ll mod)
    {
        if(n>1)
        {
            ll tmp=pow_mod(a,n>>1,mod)%mod;
            tmp=add_mod(tmp,tmp,mod);
            if(n&1) tmp=add_mod(tmp,a,mod);
            return tmp;
        }
        return a;
    }
    
    bool Miller_Rabbin(ll n,ll a)
    {
        ll d=n-1,s=0,i;
        while(!(d&1))
        {
            d>>=1;
            s++;
        }
        ll t=pow_mod(a,d,n);
        if(t==1 || t==-1)
            return 1;
        for(i=0; i<s; i++)
        {
            if(t==n-1)
                return 1;
            t=add_mod(t,t,n);
        }
        return 0;
    }
    bool is_prime(ll n)
    {
        ll i,tab[4]= {3,4,7,11};
        for(i=0; i<4; i++)
        {
            if(n==tab[i])
                return 1;
            if(!n%tab[i])
                return 0;
            if(n>tab[i] && !Miller_Rabbin(n,tab[i]))
                return 0;
        }
        return 1;
    }
    int main()
    {
    
        scanf("%lld",&T);
        while(T--)
        {
            sum=1;
            ll k=0,p;
            scanf("%lld%lld",&n,&m);
            for(int i=1; i<=n; i++)scanf("%lld",&a[i]),f[a[i]]++;;
            for(int i=1; i<=m; i++)scanf("%lld",&b),f[b]--;
            for(int i=1; i<=n; i++)
            {
                if(f[a[i]])k+=f[a[i]],f[a[i]]=0,p=a[i];
            }
            f.clear();
            if(k==1)
            {
                n=p;
                if(n<2) printf("NO
    ");
                else if(n==2) printf("YES
    ");
                else
                {
                    if(!n%2) printf("NO
    ");
                    else if(is_prime(n))
                        printf("YES
    ");
                    else printf("NO
    ");
                }
            }
            else printf("NO
    ");
        }
    }

     总的来说这题不是特别难,思想比较好。

  • 相关阅读:
    We Never Told Him He Couldn't Do It
    我是天蝎
    学习生活,有感动的时候
    .NET中AOP方便之神SheepAspect
    Effective Java (类和接口)
    Step By Step(Java 系列的目录)
    Linux Shel高级技巧(目录)
    Linux Shell经典实例解析Oracle启动脚本(下)
    Java和C++在细节上的差异(目录)
    Linux Shell经典实例解析Oracle启动脚本(上)
  • 原文地址:https://www.cnblogs.com/rmy020718/p/9311785.html
Copyright © 2011-2022 走看看