zoukankan      html  css  js  c++  java
  • HDU

    题意略:
    题解:二次剩余板子题

    //#pragma GCC optimize(2)
    //#pragma GCC optimize(3)
    //#pragma GCC optimize(4)
    //#pragma GCC optimize("unroll-loops")
    //#pragma comment(linker, "/stack:200000000")
    //#pragma GCC optimize("Ofast,no-stack-protector")
    //#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
    #include<bits/stdc++.h>
    //#include <bits/extc++.h>
    #define fi first
    #define se second
    #define db double
    #define mp make_pair
    #define pb push_back
    #define mt make_tuple
    //#define pi acos(-1.0)
    #define ll long long
    #define vi vector<int>
    #define MOD 1000000009
    #define ld long double
    //#define C 0.5772156649
    #define ls l,m,rt<<1
    #define rs m+1,r,rt<<1|1
    #define sqr(x) ((x)*(x))
    #define pll pair<ll,ll>
    #define pil pair<int,ll>
    #define pli pair<ll,int>
    #define pii pair<int,int>
    #define ull unsigned long long
    #define bpc __builtin_popcount
    #define base 1000000000000000000ll
    #define fin freopen("a.txt","r",stdin)
    #define fout freopen("a.txt","w",stdout)
    #define fio ios::sync_with_stdio(false);cin.tie(0)
    #define mr mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
    inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    //inline void sub(ll &a,ll b){a-=b;if(a<0)a+=mod;}
    //inline void add(ll &a,ll b){a+=b;if(a>=mod)a-=mod;}
    template<typename T>inline T const& MAX(T const &a,T const &b){return a>b?a:b;}
    template<typename T>inline T const& MIN(T const &a,T const &b){return a<b?a:b;}
    
    inline ll mul(ll a,ll b,ll c){return (a*b-(ll)((ld)a*b/c)*c+c)%c;}
    //inline ll qp(ll a,ll b){ll ans=1;while(b){if(b&1)ans=ans*a%mod;a=a*a%mod,b>>=1;}return ans;}
    inline ll qp(ll a,ll b,ll c){ll ans=1;while(b){if(b&1)ans=mul(ans,a,c);a=mul(a,a,c),b>>=1;}return ans;}
    
    using namespace std;
    //using namespace __gnu_pbds;
    
    const ld pi=acos(-1);
    const ull ba=233;
    const db eps=1e-5;
    const ll INF=0x3f3f3f3f3f3f3f3f;
    const int N=100000+10,maxn=2000000+10,inf=0x3f3f3f3f;
    
    ll mod;
    struct T
    {
        ll p, d;
    };
    ll w;
    //O1乘法取模黑科技
    ll mul(ll x,ll y)
    {
        return (x * y-(ll)(x /(long double)mod * y + 1e-3) * mod + mod) % mod;
    }
    //二次域乘法
    T multi_er(T a, T b)
    {
        T ans;
        ans.p = (mul(a.p, b.p) + mul(mul(a.d,b.d), w)) % mod;
        ans.d = (mul(a.p, b.d) + mul(a.d, b.p)) % mod;
        return ans;
    }
    ll quick_mod(ll a, ll b)
    {
        ll ans = 1;
        a %= mod;
        while(b)
        {
            if(b & 1)
            {
                ans = mul(ans , a);
                b--;
            }
            b >>= 1;
            a = mul(a , a);
        }
        return ans;
    }
    
    //二次域上快速幂
    T power(T a, ll b)
    {
        T ans;
        ans.p = 1;
        ans.d = 0;
        while(b)
        {
            if(b & 1)
            {
                ans = multi_er(ans, a);
                b--;
            }
            b >>= 1;
            a = multi_er(a, a);
        }
        return ans;
    }
    //求勒让德符号
    ll Legendre(ll a, ll p)
    {
        return quick_mod(a, (p-1)>>1);
    }
    ll QuadraticResidue()
    {
        ll rem = (-3 % mod + mod) % mod;
        if(rem == 0)//特判mod==3
            return 0;
        if(mod == 2)//特判非奇素数
            return 1;
        if(Legendre(rem, mod) + 1 == mod)//欧拉判别条件 非剩余
            return -1;
        ll b;
        while(1)//找一个非剩余求二次域上的单位w=sqrt(b^2 - rem)
        {
            b = rand() % mod;
            w = (mul(b, b) - rem + mod) % mod;
            if(quick_mod(w, (mod - 1)/2) + 1 == mod)//cipolla
                break;
        }
        T tmp;
        tmp.p = b;
        tmp.d = 1;
        T ans = power(tmp, (mod + 1) / 2);
        return ans.p;
    }
    
    ll a[N];
    map<ll,int>ma;
    int main()
    {
        int T;scanf("%d",&T);
        while(T--)
        {
            ll cc = 0;
            ma.clear();
            int n;ll p;scanf("%d%lld",&n,&p);
            mod = p;
            ll te=QuadraticResidue();
            for(int i=1;i<=n;i++) {
                scanf("%lld",&a[i]);
                if(a[i]) ma[a[i]]++, cc++;
            }
            if(p == 2) {
                printf("%lld
    ", cc * (cc - 1) / 2);
                continue;
            }
            if(te==-1){puts("0");continue;}
            ll ans=0;
            for(int i=1;i<=n;i++)if(a[i])
            {
                ll x=mul(a[i],(-te-1+p),p);x=mul(x,qp(2,p-2,p),p);
                ll y=mul(a[i],(te-1+p)%p,p);y=mul(y,qp(2,p-2,p),p);
                if(x==y)
                {
                    if(a[i]!=x)ans+=ma[x];
                    else ans+=ma[x]-1;
                }
                else
                {
                    if(a[i]==x)ans+=ma[x]-1;
                    else ans+=ma[x];
                    if(a[i]==y)ans+=ma[y]-1;
                    else ans+=ma[y];
                }
            }
            printf("%lld
    ",ans/2);
        }
        return 0;
    }
    /********************
    
    ********************/
    
  • 相关阅读:
    为什么使用enable_shared_from_this——shared_ptr两类错误
    More Effective C++ Item14:明智运用exception specifications
    用“双优先队列”方法解决双/多指标的规划问题
    彻底理解AC多模式匹配算法
    CentOS7安装MySQL
    CentOS7配置本地Yum源
    数组
    比较运算符
    申明变量
    相等运算符==与等同运算符===
  • 原文地址:https://www.cnblogs.com/acjiumeng/p/11128600.html
Copyright © 2011-2022 走看看