UVA

来源:互联网 发布:excel转pdf软件 编辑:程序博客网 时间:2024/05/16 15:52

题目链接:https://vjudge.net/problem/UVA-1635

题目大意:对于一列数,比如a1,a2,a3,a4,a5,转化成a1+a2,a2+a3,a3+a4,a4+a5,转化成a1+2a2+a3,a2+2a3+a4,a3+2a4+a5,转化成a1+3a2+3a3+a4,a2+3a3+3a4+a5,转化成a1+4a2+6a3+4a4+a5,输出系数能被m整除的数的下标

解题思路:可以知道答案就是杨辉三角的系数,然后要比较每个系数是否能被m整除,一开始想到的是用逆元快速幂,但是m不一定满足逆元条件,所以只能用唯一分解定理,由于C(n,k)可以由C(n,k-1)递推而来,所以可以算出每个的素因子及系数,再与m分解后的素数相应的系数比较,一开始是无脑分解,把C(n,k)的素因子全分解了,但是超时,后来发现,其实只需要分解m对应的素数即可

AC代码:

#include<cstdio>#include<map>using namespace std;const int MAXN = 1000000 + 5;int anstot, ans[MAXN];int primetot, prime[MAXN];bool vis[MAXN];map<int, int> mp, np;void getPrime(){    primetot = 0;    for (int i = 2;i < MAXN;i++)    {        if (!vis[i]) prime[primetot++] = i;        for (int j = 0;j < primetot&&prime[j] * i < MAXN;j++)        {            vis[prime[j] * i] = 1;            if (i%prime[j] == 0) break;        }    }}void getChange(int n, int flag, map<int, int>& mp){    for (int i = 0;i < primetot&&prime[i] <= n;i++)    {        while (n%prime[i] == 0)        {            n /= prime[i];            mp[prime[i]] += flag;        }    }    if (n > 1)        mp[n] += flag;}void toCal(int n, int m){    anstot = 0;    mp.clear();    np.clear();    getChange(m, -1, mp);    for (int i = 1;i < n;i++)    {        int a = n - i + 1, b = i;        bool flag = 1;        for (map<int, int>::iterator it = mp.begin();it != mp.end();it++)        {            while (a % (it->first) == 0)                np[it->first]++,a /= (it->first);            while (b % (it->first) == 0)                np[it->first]--,b /= (it->first);            if (np[it->first] + it->second < 0)                flag = 0;        }        if (flag)            ans[anstot++] = i + 1;    }}int main(){    getPrime();    for (int n, m;scanf("%d%d", &n, &m) == 2;)    {        toCal(n - 1, m);        printf("%d\n", anstot);        for (int i = 0;i < anstot;i++)        {            if (i != 0) printf(" ");            printf("%d", ans[i]);        }        puts("");    }    return 0;}