zoukankan      html  css  js  c++  java
  • 【UVA1635】哑元

    题意

    给定n个数a1,a2,...an,依次求出相邻两数之和,将得到一个新数列。重复上述操作,最后结果将变成一个数。问这个数除以m的余数与哪些数无关?例如n=3,m=2时,第一次求和得到a1+a2,a2+a3,再求和得到a1+2a2+a3,它除以2的余数和a2无关。(1 ≤ n ≤ 100 000, 2 ≤ m ≤ 109 )

    分析

    举的这个例子已经疯狂暗示了,怎么看都是二项式定理啊!!!

    二项式定理就不写了,反正就是求组合数了,有一个递推的式子

    证明太显然了,直接拆成递推形式一眼就看出来了。于是可以利用它计算出C(n-1,i-1)的每一项,得到ai的系数,再判断一下是不是m的倍数

    直接递推太大了,会涉及到高精,于是利用唯一分解定理分解m,再比较各个质因子的指数与C(n-1,i-1)中的指数即可。

    代码

    1. #include<bits/stdc++.h>  
    2. using namespace std;  
    3. #define N 100010  
    4. int n,m,cnt;  
    5. int p[N],c[N],ok[N];  
    6. vector<int>ans;  
    7. void divide(int k)  
    8. {  
    9.     cnt=0;  
    10.     memset(p,0,sizeof(p));  
    11.     memset(c,0,sizeof(c));  
    12.     int mx=(int)sqrt(k+1);  
    13.     for(int i=2;i<=mx;i++)  
    14.     {  
    15.         if(k%i==0)  
    16.         {  
    17.             p[++cnt]=i;  
    18.             while(k%i==0)c[cnt]++,k/=i;  
    19.         }  
    20.         if(k==1)break;  
    21.     }  
    22.     if(k>1)p[++cnt]=k,c[cnt]=1;   
    23. }  
    24.   
    25. vector<int> solve()  
    26. {  
    27.     memset(ok,-1,sizeof(ok));  
    28.     vector<int>v;n--;  
    29.     for(int i=1;i<=cnt;i++)  
    30.     {  
    31.         int cm=0;  
    32.         for(int k=1;k<n;k++)  
    33.         {  
    34.             int a=n-k+1,b=k;  
    35.             while(a%p[i]==0)a/=p[i],cm++;  
    36.             while(b%p[i]==0)b/=p[i],cm--;  
    37.             if(cm<c[i])ok[k]=0;  
    38.         }  
    39.     }  
    40.     for(int i=1;i<n;i++)if(ok[i])v.push_back(i+1);  
    41.     return v;  
    42. }  
    43.   
    44. int main()  
    45. {  
    46.     while(scanf("%d%d",&n,&m)==2)  
    47.     {  
    48.         divide(m);  
    49.         ans=solve();  
    50.         printf("%d ", (int)ans.size());  
    51.         for (int i = 0; i < ans.size(); i++)   
    52.             printf("%d%c",ans[i],i==ans.size()-1?' ':' ');  
    53.         if (ans.size()==0) printf(" ");   
    54.     }  
    55.     return 0;  
    56. }  
  • 相关阅读:
    BZOJ3197:[SDOI2013]刺客信条——题解
    C 程序与 C++ 程序之间的相互调用
    使用Dev C++调试(debug)程序
    ARM 汇编指令 ADR 与 LDR 使用
    华为交换机以 LACP 模式实现链路聚合
    DLCI 简介
    华为路由器帧中继 FR 实验
    GVRP 的工作机制和工作模式
    华为路由器 HDLC 实验
    华为路由器 IPSec 与 GRE 结合实验
  • 原文地址:https://www.cnblogs.com/NSD-email0820/p/9865529.html
Copyright © 2011-2022 走看看