• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            pku3904 容斥原理的運(yùn)用,好題!

            解法發(fā)現(xiàn)網(wǎng)上一個大牛寫的很好,就轉(zhuǎn)載過來吧。可憐的我,開始沒想到算法就算了,想到算法后又刻意依賴STL結(jié)果o(N)寫成o(logN)成功葬送。
            解法

            題意:給你n個數(shù),求GCD(gcd(a,b),gcd(c,d))=1的方案數(shù),注意a,b,c,d并不一定兩兩互質(zhì),有多組數(shù)據(jù)

            本來這個題的題解有一大把,但沒有講題解的只有貼代碼的。

            本來一直在做題,沒有什么時間發(fā)題解,但這個題加深了我對容斥原理的理解,所以講一下

            這個題的算法是個偽多項(xiàng)式

            首先,先將算法流程說一下,原理后面會有

            Step 1:用篩法篩出10000內(nèi)的素數(shù)表

            Step 2:組合素數(shù),用bool數(shù)組記錄由m(m<=5)個素數(shù)相乘所得數(shù)的m的奇偶

            例如:182=2*7*13 ———> m=3 so,bool[182]=false

                        2=2 ——>m=1 so,bool[2]=false

                        91=7*13 ——>m=2 so,bool[91]=true

                        注意12=2^2*3等這種是B=p1^k1*p2^k2+...這種有質(zhì)因數(shù)指數(shù)不為一的合數(shù)不要處理因?yàn)椴粫玫?/p>

            以上是預(yù)處理

            Step 3:讀入當(dāng)前數(shù)為a,將a分解為質(zhì)因數(shù)形式,注意每個質(zhì)因數(shù)只被記錄一次

            例如:12=2*2*3 則 12會被分為2*3,多余的2被消去了

            Step 4:將分出的素數(shù)進(jìn)行組合,將組合出的a的約數(shù)的time+1

            例如:12=2^2*3——>12=2*3——>time[2]++,time[3]++,time[6]++

            Step 5:處理之后,ans賦值為C(n,4)即n*(n-1)*(n-2)*(n-3)div 24

            Step 6:for i 2-->10000

                            if bool[i] then ans:=ans-C(time[i],4)

                                           else ans:=and+C(time[i],4);

            Step 7:輸出ans


            原理:首先考慮一個問題,1000以內(nèi)6,7,8,9的倍數(shù)有多少個?答案是

            1000div6+1000div7+1000div8+1000div9

            -1000div(6*7)-1000div(6*8)-1000div(6*9)-1000div(7*8)-1000div(7*9)-1000div(8*9)

            +1000div(6*7*8)+1000div(6*8*9)+1000div(7*8*9)

            -1000div(6*7*8*9)

            這是容斥原理的一個最簡單的應(yīng)用,類比這道題,Step3到4其實(shí)將每個數(shù)a的不重復(fù)約數(shù)記錄了下來,有公共約數(shù)的四個數(shù)的方案要從ans中減去,多減的要加上

            顯然m為奇時要減,m為偶時要加,這和”1000以內(nèi)6,7,8,9的倍數(shù)有多少個?“這個問題奇偶是反的,由于a最大為10000,所以m最大可以有5 (2*3*5*7*11<10000,2*3*5*7*11*13>10000)

            至于12=2*2*3這種約數(shù)不處理因?yàn)榭梢苑譃?*6,而2和6會算一次,所以不須再算。


            代碼:
             1 # include <cstdio>
             2 # include <map>
             3 # include <cstring>
             4 # include <algorithm>
             5 using namespace std;
             6 int pa[2000],pp=0,sa[10],sp=0;
             7 int refer[5][10001];
             8 void make_prime()
             9 {
            10     bool used[10001];
            11     memset(used,true,sizeof(used));
            12     for(int i=2;i<=10000;i++)
            13          if(used[i])
            14          {
            15              pa[pp++]=i;
            16              for(int j=2*i;j<=10000;j+=i)
            17                 used[j]=false;
            18          }
            19 }
            20 void spilt(int n)
            21 {
            22     sp=0;
            23     for(int i=0;i<pp&&n!=1;i++)
            24         if(n%pa[i]==0)
            25         {
            26             sa[sp++]=pa[i];
            27             while(n%pa[i]==0)
            28                 n/=pa[i];
            29         }
            30 }
            31 void putmap(int n)
            32 {
            33     spilt(n);
            34     for(int i=1;i<(1<<sp);i++)
            35     {
            36         int n1=0,n2=1;
            37         for(int j=0;j<5;j++)
            38             if(i&(1<<j))
            39                 n1++,n2*=sa[j];
            40         refer[n1-1][n2]++;
            41     }
            42 }
            43 long long c(int n)
            44 {
            45     return (long long)n*(n-1)*(n-2)*(n-3)/4/3/2;
            46 }
            47 long long getans(int n)
            48 {
            49     long long ans=c(n);
            50     for(int i=0;i<5;i++)
            51     {
            52         bool flag=false;
            53         for(int j=1;j<=10000;j++)
            54             if(refer[i][j]>=4)
            55                 flag=true,
            56                 ans+=c(refer[i][j])*(i%2?1ll:-1ll);
            57         if(!flag)break;
            58     }
            59     return ans;
            60 }
            61 int main()
            62 {
            63     int n;
            64     make_prime();
            65     while(scanf("%d",&n)!=EOF)
            66     {
            67         memset(refer,0,sizeof(refer));
            68         for(int i=0;i<n;i++)
            69         {
            70             int t;
            71             scanf("%d",&t);
            72             putmap(t);
            73         }
            74         printf("%lld\n",getans(n));
            75     }
            76     return 0;
            77 }

            posted on 2012-02-17 02:03 yzhw 閱讀(408) 評論(0)  編輯 收藏 引用 所屬分類: combination math

            <2010年12月>
            2829301234
            567891011
            12131415161718
            19202122232425
            2627282930311
            2345678

            導(dǎo)航

            統(tǒng)計

            公告

            統(tǒng)計系統(tǒng)

            留言簿(1)

            隨筆分類(227)

            文章分類(2)

            OJ

            最新隨筆

            搜索

            積分與排名

            最新評論

            閱讀排行榜

            久久精品亚洲精品国产欧美| 久久97久久97精品免视看| 国产高潮久久免费观看| 久久精品不卡| 区亚洲欧美一级久久精品亚洲精品成人网久久久久| 国产69精品久久久久9999| 欧美日韩精品久久久久| 久久精品99久久香蕉国产色戒| 久久亚洲精品无码AV红樱桃| 婷婷综合久久中文字幕| 香蕉aa三级久久毛片| 久久精品青青草原伊人| 久久九九有精品国产23百花影院| 欧美久久一区二区三区| 天天躁日日躁狠狠久久| 久久无码高潮喷水| 久久天天躁狠狠躁夜夜2020 | 日本道色综合久久影院| 性做久久久久久久久久久| 久久水蜜桃亚洲av无码精品麻豆| 国内精品久久久久国产盗摄| 99久久精品国产一区二区| 国产免费久久精品99re丫y| 日韩一区二区久久久久久| 亚洲av日韩精品久久久久久a| 久久久久亚洲AV无码去区首| 99久久99久久精品国产片| 日本久久久久亚洲中字幕| 国产免费久久精品99re丫y| 久久精品二区| 久久五月精品中文字幕| 久久99国产精一区二区三区| 久久精品国产精品青草app| 久久亚洲春色中文字幕久久久| 久久久久久久久波多野高潮| 久久播电影网| 久久久久久久91精品免费观看 | 色欲综合久久躁天天躁蜜桃| 久久综合精品国产一区二区三区| 91久久九九无码成人网站| 久久精品国产秦先生|