杨辉三角与二项式定理的应用

给定n个数a1,a2····an,依次求出相邻两个数值和,将得到一个新数列,重复上述操作,最后结果将变为一个数,问这个数除以m的余数与那些数无关?例如n=3,m=2时,第一次得到a1+a2,a2+a3,在求和得到a1+2*a2+a3,它除以2的余数和a2无关。1=<n<=10^5, 2=<m<=10^9

 

思路分析 :

  看一下 n 的范围是 10^5 , 在二项式定理中又有这个公式

所以很容易在 O(n)的时间内推出所有项的系数,但是越往后面推 ,数会越大,爆掉 long long ,因此我们得换个方法

对 m 用唯一分解定理,那么接下来判断一个数是不是 m 的倍数,只需要判断这个数分解出的所有项的指数是否都大于等于 m 的即可

!!! 在用到容器的时候,如果有循环读入,一定要记得清空,不然一直超时

!!! 这个题最后输出的地方也好坑呀... 一直PE

代码示例 :

#define ll long long
const ll maxn = 1e6+5;
const ll mod = 1e9+7;
const double eps = 1e-9;
const double pi = acos(-1.0);
const ll inf = 0x3f3f3f3f;

vector<ll>prime;
ll e[1000], f[1000];
ll n, m;
ll k = 0;

void init(){
     k = 0;
    prime.clear();
    memset(f, 0, sizeof(f));
    memset(e, 0, sizeof(e));
    for(ll i = 2; i <= sqrt(m); i++){
        if (m % i == 0){
            prime.push_back(i);
            while(m % i == 0) {
                m /= i;
                e[k]++;    
            }
            k++;
        }
    }
    if (m != 1) {
        prime.push_back(m);
        e[k]++;
    }
    //prllf("++++ %d\n", e[0]);
}

void add(ll x, ll d){
    
    for(ll i = 0; i < prime.size(); i++){
        
        ll su = prime[i]; 
        while (x%su == 0){
            f[i] += d;
            x /= su;
        }
    }
}

bool check(){
    for(ll i = 0; i < prime.size(); i++){
        if (f[i] < e[i]) return false;
    }
    return true;
}
vector<ll>ans;

int main() {
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
    
    while(cin >> n >> m){ 
        init();
        n--;
        ans.clear();
        for(ll i = 1; i < n; i++){
            add(n-i+1, 1);
            add(i, -1);
            if (check()) ans.push_back(i+1);
        }
        printf("%d\n", ans.size());
        for(ll i = 0; i < ans.size(); i++){
            printf("%lld%c", ans[i], i==ans.size()-1?'\n':' ');
        }
        if (ans.size() == 0) printf("\n");
    }
    return 0;
}

 

posted @ 2018-04-24 13:50  楼主好菜啊  阅读(576)  评论(0编辑  收藏  举报