【JZOJ6272] 2019年8月4日[グループA] NOIP割り切れる改善

タイトル

効果の対象に

(\(X ^ MX)\ MOD N = 0 \) の整数の範囲内([1、N] \ \ ) ソリューションの番号。
\(N = \ sum_ {I
= 1} ^ {C} P_I \)が与えられている\(C \)\(P_I \)


歴史上のものがたり

数論の馬鹿として、あなたは自閉症のゲームでこの質問を見たいと思って......
混乱波動方程式を押し、後者は従事しません。
だから私は出てくるしたくなかった......サブ部門の一部でも結果を部分に望んでいました。
直接呼び出す\(20 \)暴力ポイント。


正解

式は、に分割することができる(C \)\(各式\(Iは\) :)\ ((X = 0 \ ^ MX)\ P_I MOD)が
それぞれ合同式について解かれます。場合列挙ソリューション\(X \) 及び各\(X ^ Mの\)それを処理します。
高速パワーはTLEので、見つけるために、乗法ふるい方法を使用します(X- ^ m個\)\具体的には、関数\(F(X)= X ^ Mの\)は乗法関数です。したがって、電源をフラッシュすることにより得られる\(X \)素数である\(X ^ Mの\)は、共関数値の数は、2つの因子によって乗算されます。
この時間の複雑さはオフになっています。
生成物溶液のうち処理後==各合同式の数は==全体合同の方程式の解の数です。

プルーフ;
式ため\((X ^ MX)P_I MOD = 0 \ \) 解集合のための\(X_ {I、1}
、X_ {I、2}、···、X_ {I、S_I} \) 各式は、溶液に引き寄せと呼ばれた\(X_I \)、\ (X_I \)\(X_ {I、1..s_i} \) の溶液。
方程式の解は次のように設定されている(X- \)\
次いで\(X-を\) それぞれについて以下の式を満足\(Iは\) ):\
(X- \当X_I(\ MOD P_I)\)
中国の剰余定理に従ってこの式は、唯一の解決策となります。
方程式とのソリューション\(X_1、X_2、...、 X_C \) の値は、一から一(これは感情的な理解することができます)です。
以下のための\(X_I \) そこに\(S_I \)可能な値。乗算の原則によると、ソリューションの合同方程式の数は、各合同方程式の解の数だけの製品です。

その後、私は、より強力な方法ということを学びました。
同じことが、求めている(\(^ X MX)\を = 0 \ MOD P_I) 解の数であるが、今回は暴力を求めていません。
そこ性質:ソリューションの数が等しい(\ \ GCD(1-M ,. 1-P_I)+ +1を\)
便宜上、直接背後(P_I \)\添字を省略。)

証明:
原稿を書くことができる\(X-当\ X- ^ M(\ P-MOD)\)
\(P-2 = \)時間が明確に確立されています。
\(X = 0 \)明確方程式の解である
区間でのソリューションを検討する\([1、P-1 ] \) の値
により\(P \)は奇素数であるので、原始根が存在しなければなりません。プリミティブルートが設定されている\(G \)
式のように表すことができる\(G ^ {YM} \の
当量のG ^ Y(\ MOD P)\) フェルマーの小定理用のY(\ \(YM \当量のMOD(P- 1))\)
されている\(Y(M-1)
\当量0(\ MOD(P-1))\) に配置された\(K = \ GCD(M-1、P-1)\) で除算しながら辺は\(K \)を得た\(Y用の\ FRAC {M 1
- {K} \当量0(\ MOD \ FRAC {P-1} {K})\}) ので\(\ GCD(\ FRACを{M-1} {K}、\ FRAC {K})= 1 \){P-1}。ので、\(\ FRAC {P-1
} {K} | Yの\) ので\(Y \)がある\ (\ FRAC {P-1} {K} \) 複数、明らかに取ることができます\(0 \)する\(K-1 \)倍、すなわち\(Y \)をしている(K \)\溶液目。
だから、\(X \)もいる\(k個\)ソリューション。
したがって、解の数である(\ \ GCD(M-1 、P_I-1)+1 \)

このプロパティを使用すると、プログラムが速い(標準的なプロセスで爆発的ステップ)に起動される......


コード

解決するために暴力:
(データはとにかくいくつかの小さな画面ワイヤーふるい定数エリクセンを打つのが面倒なので、狭い範囲。)

using namespace std;
#include <cstdio>
#include <cstring>
#include <algorithm>
#define mo 998244353
#define P 10000
int id;
int c,m;
int n;
inline int my_pow(int x,int y,int p){
    int res=1;
    for (;y && res;y>>=1,x=x*x%p)
        if (y&1)
            res=res*x%p;
    return res;
}
int di[P+1];
int xm[P+1];
inline void init(){
    di[1]=1;
    for (register int i=2;i<=P;++i){
        if (di[i])
            continue;
        di[i]=i;
        for (int j=i*i;j<=P;j+=i)
            di[j]=i;
    }
}
inline int work(int p){
    int res=2;
    xm[0]=0,xm[1]=1;
    for (register int i=2;i<=p;++i){
        xm[i]=(di[i]==i?my_pow(i,m,p):xm[i/di[i]]*xm[di[i]]%p);
        res+=(xm[i]==i);
    }
    return res;
}
int main(){
    freopen("division.in","r",stdin);
    freopen("division.out","w",stdout);
    int T;
    scanf("%d%d",&id,&T);
    init();
    while (T--){
        scanf("%d%d",&c,&m);
        long long ans=1;
        for (int i=1;i<=c;++i){
            int p;
            scanf("%d",&p);
            ans=ans*work(p)%mo;
        }   
        printf("%lld\n",ans);
    }
    return 0;
}

高速ハードウェア・ソリューション:

using namespace std;
#include <cstdio>
#include <cstring>
#include <algorithm>
#define mo 998244353
inline int gcd(int a,int b){
    int k;
    while (b){
        k=a%b;
        a=b;
        b=k;
    }
    return a;
}
int main(){
    freopen("division.in","r",stdin);
    freopen("division.out","w",stdout);
    int T;
    scanf("%*d%d",&T);
    while (T--){
        int c,m;
        scanf("%d%d",&c,&m);
        long long ans=1;
        while (c--){
            int p;
            scanf("%d",&p);
            ans=ans*(gcd(p-1,m-1)+1)%mo;
        }   
        printf("%lld\n",ans);
    }
    return 0;
}

概要

それはまだあまりにも料理...... QWQ私の数論のようだ......

おすすめ

転載: www.cnblogs.com/jz-597/p/11299882.html