• ZOJ2666 Irrelevant Elements [数论]


    是道有意思的题,在LRJ的杂题中有提到,题意是这样的:有n(n<=10^5)个数,每个数在[0,m), m <= 10^9中随机选一个数,对这n个数,做这样的操作,相邻的两个数求和后变成n-1个数,然后迭代到只剩下一个数,对这最后的数%m,问说哪个数是跟最后的数是没有影响的。

    设这几个数是a,b,c,d->a+b,b+c,c+d->a+2b+c,b+2c+d->a+3b+3c+d,因此对于这n个数a1,a2,…,an,迭代到最后的ans=C(n-1,0)*a1+C(n-1,1)*a2+C(n-1,2)*a3+…+C(n-1,n-1)*an,因此当C(n-1,i)%m=0, i∈[0,n-1]的时候,ans对于该数是无关的。

    因此,需要解决一个这样的问题,判断C(a, b)%m是否等于0,我们知道C(a, b)=a!/b!/(a-b)!,我们可以先筛出sqrt(m)以内的素数,复杂度O(sqrt(m)),然后把m进行质因数分解,复杂度O(logm),然后把a!,b!,(a-b)!分别素因数(考虑m的素因数就可以了)分解,复杂度O(logm*logn),然后判断,是否包含m的素因数就可以了,因此最后的复杂度为O(N*logm*logn),代码如下:

    #include <iostream>
    #include <string>
    #include <algorithm>
    #include <vector>
    #include <set>
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    #include <string.h>
    #include <map>
    using namespace std;
     
    const int MAXN = 100005;
    const int MAXM = 1e9 + 5;
     
    //map<int, int> map_n[MAXN];    //N!质因数分解
     
     
    int n, m;
    int s[MAXN];
    vector<int> prime;
     
    void make_prime()
    {
        prime.clear();
        memset(s, 0, sizeof(s));
        //1...N之前的质数
        //复杂度约等于N*lg(N)
        for(int i = 2; i < MAXN; i++)
        {
            if(s[i] == 0)
            {
                prime.push_back(i);
                for(int j = i + i; j < MAXN; j += i)
                    s[j] = 1;
            }
        }
    }
     
    void go()
    {
        vector<map<int, int> > map_n;
        map<int, int> map_m;    //M的分解
        //分解M
        //复杂度lg(M)
        //初始化
        map_m.clear();
        int t_m = m;
        for(int i = 0; i < prime.size() && prime[i] <= sqrt(m * 1.0); i++)
        {
            int p = prime[i];
            if(t_m % p == 0)
            {
                while(t_m % p == 0)
                {
                    map_m[p]++;
                    t_m /= p;
                }
            }
        }
        if(t_m != 1)  map_m[t_m]++;
     
        //分解1...N的阶乘的质因数,这里其实只用分级M的质因数就可以了
        //否则复杂度就是N*O(N)*lg(N)了,O(N)表示N之前的质数 
        //复杂度N*lg(M)*lg(N)
        
        
        map_n.clear();
        map_n.resize(n + 1);
        for(int i = 0; i <= n; i++)
        {
            //初始化
            //map_n[i].clear();
     
            int j = i;
            //for(int k = 0; k < prime.size() && prime[k] <= j; k++)
            for(map<int, int>::iterator it = map_m.begin(); it != map_m.end(); it++)
            {
                int N = j, p = it->first;
                if(p > N)  break;
                while(N)
                {
                    map_n[i][p] += N / p;
                    N /= p;
                }
            }
        }
     
     
        vector<int> ans;
        map<int, int>::iterator it;
     
        //复杂度为N*lg(M)
        //枚举解X
        
        //printf("count = %d\n", map_m.size());
        for(int i = 0; i <= n; i++)
        {
            //枚举M的质因数
            for(it = map_m.begin(); it != map_m.end(); it++)
            {
                int p = it->first;
                int cnt = it->second;
     
                if(map_n[n][p] - map_n[i][p] - map_n[n - i][p] < cnt)
                    break;
            }
            if(it != map_m.end())  continue;
            ans.push_back(i + 1);
        }
     
        printf("%d\n", ans.size());
        
        for(int i = 0; i < ans.size(); i++)
        {
            if(i == 0)  printf("%d", ans[i]);
            else  printf(" %d", ans[i]);
            //printf("%d ", ans[i]);
        }
        printf("\n");
        
    }
     
    int main()
    {
        make_prime();
        while(scanf("%d%d", &n, &m) != EOF)
        {
            --n;
            //求C(N, X)%M=0,X=[0, N],解X的个数
            //ready();
            //debug();
            go();
        }
    }
  • 相关阅读:
    矩阵树定理
    随机乱搞算法
    数学
    BZOJ——3412: [Usaco2009 Dec]Music Notes乐谱
    BZOJ—— 3402: [Usaco2009 Open]Hide and Seek 捉迷藏
    洛谷—— P2884 [USACO07MAR]每月的费用Monthly Expense
    洛谷—— P2417 课程
    洛谷—— P1577 切绳子
    COGS 2598. 美丽的感觉
    10.23 模拟赛
  • 原文地址:https://www.cnblogs.com/litstrong/p/2022634.html
Copyright © 2020-2023  润新知