日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

唯一分解定理(算术基本定理)详解——hdu5248和lightoj1341

發布時間:2025/3/20 编程问答 16 豆豆
生活随笔 收集整理的這篇文章主要介紹了 唯一分解定理(算术基本定理)详解——hdu5248和lightoj1341 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

算數分解定理(唯一分解定理):

定義:

任何一個大于1的自然數 N,如果N不為質數,那么N可以唯一分解成有限個質數的乘積 N=P1a1 P2a2P3a3…Pnan,這里P1<P2<P3…<Pn均為質數,其中指數ai是正整數。這樣的分解稱為 N 的標準分解式.

應用:對于一個正整數n,如果n=q1a1 * q2 a2 * …* qnan,那么他的正因數個數為(1 a1) * (1 a2)* . . . *(1 an);

樣例:

1000=2* 500=2* (2 * 250)=2 * 2 *( 2 * 125)=2 * 2 * 2 *(5 * 25)=2 * 2 * 2 * 5 * (5 *5)=23*53.可以看的出來基本策略就是從2開始除,直到不是2的倍數然后網上遞增求。

計算方法:

計算n的分解方式。主要是通過數的自身對從最小的質數開始整除除一直到不能整除,直到跳出限制條件。

  • 你可以從2到n;逐個遍歷判斷,滿足條件的話就在數組中添加對應的count。當然,每被計算一次的時候,這個數就要被除一次。

  • 上面方法對于大的數據顯然復雜度太高。其實你可以從2遍歷到根號n 1(i * i<n 1)停止,因為最大的理想乘積是i*i=n,其他的數據都是一個左,一個右面。最終分解的時候如果都分到這步了說明要么后面不剩,要么就是剩一個大質數

  • 上面雖然從數的量級減少了不少,但是會遍歷很多沒用的合數,比如遍歷過2所有而的倍數都不需要遍歷判斷,所以我們只需要遍歷素數。素數打表遍歷素數,當遇到多組輸入,數據要求較高的時候,先用素數篩打表,把素數預處理,然后直接從2-素數數組中遍歷即可,因為如果一個數能被拆,那么他如果不能被拆,他就是素數,如果它還能被拆,那么它就是合數。所以一個數被分解到最后都是素數的次冪相乘!很重要!這樣能夠省的更多的時間。可以參考素數篩模板。

  • 核心代碼:
    不打表:

    for(int j=2;jj<n+1;j++) {while(n%j==0){n/=j;//根據需求操作}//根據需求操作...}

    打表:

    static int index=0;//根據數據范圍范圍內素數的最后一個位置prime[index] long prime[]=new long[100001]; boolean isprime[]=new boolean[1000001]; for(int i=2;i<1000001;i++)//埃拉托色尼篩選法 {if(!isprime[i]){prime[index ++]=i;for(int j=i+i;j<1000000;j=j+i){isprime[j]=true; }} } ........ ........// int n;for(int j=0;j<index;j++){if(n==0||prime[j]>n) {break;}//素數已經超出無法最大的數,退出long team=0;//其他操作,可以是你自己的邏輯while(c%prime[j]==0){c/=prime[j];team++ ;//其他操作}number*=(1+ team);//其他操作}

    唯一分解定義有什么用?

    • 例如給一個1000,這樣的數,問有多少種可能組合使得a * b=1000.或者求a*b中在那個范圍內a,b的排列次數。

    • 首先要了解一個唯一分解定理的應用:對于一個正整數n,如果n=q1a1 * q2 a2 * …* qnan,那么他的正因數個數為(1 a1) * (1 a2)…(1 an);對于這個,就可以衍生其他問題,比如找兩個因數的組合情況,可能性,在那個范圍等等。其實這就是一個組合問題。對于每一個數有t個,能夠影響最終結果的就是這個素數出現的次數。如果細看雖然每個數的概率都是可能出現和不出現的1/2.但是對于最終結果就是:出現0次,出現1次,出現。。。,出現t次。所以這個數對結果出現的可能行變成了原來次數*(1 t).以此類推,便可得到所有的因數可能的結果。

    • 就例如1000=23 * 53:
      對于結果首先2和5是獨立互不影響的。所以對于一個因數。質數2的搭配有四種,出現0個,1個,2個或3個。同理質數5的搭配也是4種,所以最終因數可能出現的次數是4 * 4=1*(3 1)*(3 1)=16個。

    例題

    看下hdu5248

    題意:給出n個數,求這n個數中最小的兩個因數乘積,題意有些小的歧義不太好理解。說明白了就是讓你從n個數分解找最小的兩個因子相乘.(1不滿足因為1沒有2個及以上因子).

    思路:數據量不大,可以不打表直接素數分解。其實每個數找到2個因子就可以停止了,放到list或者數組中,最后排序判斷因子是否大于等于2個。按照要求輸出

    附上ac代碼:

    import java.util.ArrayList; import java.util.List; import java.util.Scanner;public class hdu5248 {public static void main(String[] args) {Scanner sc=new Scanner(System.in);int T=sc.nextInt();for(int q=0;q<T;q++ ){int n=sc.nextInt();List<Long>list=new ArrayList<Long>();for(int i=0;i<n;i++){long te=sc.nextLong();int num=0;for(int j=2;(long)j*j<te+1;j++ ){while(te%j==0){list.add((long) j);te/=j;num ;}if(num>2)break;//其實找到兩個就不用找了}if(te>1) {list.add(te);}}if(list.size()<2)System.out.println(-1);else {list.sort(null);System.out.println((long)(list.get(0)*list.get(1)));}}} }

    lightoj1341
    題目大意:給個面積s。一個邊b,問最小邊大于b的所有可能情況。
    思路:整體-多余。先求出所有的排列次數,然后除以二(要求組合隊數)。再從0頭到b開始剪掉多余的情況。不需要考慮特大的那邊,因為是對稱的已經除以過二了。
    ac代碼:

    埃氏篩

    import java.util.Scanner; public class testC { static int index=0; public static void main(String[] args) {// TODO 自動生成的方法存根long prime[]=new long[100001];boolean isprime[]=new boolean[1000001];for(int i=2;i<1000001;i++)//埃拉托色尼篩選法{if(!isprime[i]){prime[index++]=i;for(int j=i +i;j<1000000;j=j+i){isprime[j]=true; }}}Scanner sc=new Scanner(System.in);int t=sc.nextInt();for(int i=0;i<t;i++){long a=sc.nextLong();long b=sc.nextLong();long number=1;long c=a;if(b*b>=a) {number=0;}//不可能的情況,最小邊大于可能拼成的情況else {for(int j=0;j<index;j++){if(c==0||prime[j]>c) {break;}//超出界,跳出long team=0;while(c%prime[j]==0){c/=prime[j];team++;}number*=(1+team);//計算} if(c>1)number*=2;number/=2;//這里別被繞進去。這里不是按照次冪計算的,而是按照實打實的一個一個數判斷的。for(int j=1;j<b;j++){if(a%j==0)number--;}}System.out.println("Case " (i+1) ": " +number);} }}

    歐拉篩:

    import java.util.Scanner;public class testC {static int index=0;public static void main(String[] args) {// TODO 自動生成的方法存根int prime[] = new int[100001];// 記錄第幾個primeint index = 0;boolean isprime[] = new boolean[1000001];for (int i = 2; i < 1000001; i++) {if (!isprime[i]) {prime[index++] = i;}for (int j = 0; j < index && i * prime[j] < 1000001; j++) {isprime[i * prime[j]] = true;// 找到的素數的倍數不訪問if (i % prime[j] == 0)break;// 關鍵!!!!}}Scanner sc=new Scanner(System.in);int t=sc.nextInt();for(int i=0;i<t;i++){long a=sc.nextLong();long b=sc.nextLong();long number=1;long c=a;if(b*b>=a) {number=0;}//不可能的情況,最小邊大于可能拼成的情況else {for(int j=0;j<index;j++){if(c==0||prime[j]>c) {break;}long team=0;while(c%prime[j]==0){c/=prime[j];team++;}number*=(1+team);} if(c>1)number*=2;number/=2;for(int j=1;j<b;j++){if(a%j==0)number--;}}System.out.println("Case " (i+1) ": " +number);}} }
    • 如果對后端、爬蟲、數據結構算法等感性趣歡迎關注我的個人公眾號交流:bigsai

    總結

    以上是生活随笔為你收集整理的唯一分解定理(算术基本定理)详解——hdu5248和lightoj1341的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。