UVa1635
我們很容易發現最后每一項的系數就是二項式展開,余數和m沒有關系就意味著可以被m整除,因此我們就需要求出每一個二項式的系數。但是數據實在太大我們根據唯一分解定理將m和系數都進行分解,然后比較因子的冪。
二項式的計算我們可以根據楊輝三角遞推,可是這個實在是太大了,遞推很慢。
所以我們要知道二項式的另一個遞推式:C(n,k)=C(n,k-1)*(n-k+1)/k,遞推出需要的素數的分解式。
我們發現判斷每一個系數是否能夠被m整除需要將所有的因子進行比較,如果不處理的話109需要105 的素數表,每一次都是105的比較,這樣太耗時了,很多操作都是沒有意義的(因為m根本沒有那么多因子)。為了優化,我們用一個表記錄m的所有素因子和每個因子出現的次數,然后再用另一個數組記錄系數中這些因子出現的次數,這樣就可以大大提升時間效率。
輸出為0的時候要多輸出一個換行,需要注意。
#include<cstdio> #include<cstring> #include<algorithm> #include<climits> #include<cctype> #include<queue> #include<set> #include<cmath>using namespace std;typedef long long ll; const int INF=0x3f3f3f3f; const int MAXN=1e5+5; bool check[MAXN]; int prime[MAXN]; int cnt1[MAXN]; int cnt2[MAXN]; int tmp[MAXN]; int ans[MAXN]; int num,tot,top; int n,m;void creat_prime() {tot=0;for(int i=2;i<MAXN;i++){if(!check[i]) prime[tot++]=i;for(int j=0;j<tot && prime[j]*i<MAXN ;j++){check[prime[j]*i]=true;if(i%prime[j]==0) break;}} }bool ok() {for(int i=0;i<top;i++){if(cnt2[i]>tmp[i]) return false;}return true; }void deal(int x,int d) {for(int i=0;i<top;i++){while(x%cnt1[i]==0){tmp[i]+=d;x/=cnt1[i];}if(x==1) break;} }int first=1;int main() {//freopen("data.out","w",stdout);creat_prime();while(~scanf("%d%d",&n,&m)){num=0; top=0;memset(cnt2,0,sizeof(cnt2));for(int i=0;i<tot;i++){if(m%prime[i]==0){cnt1[top]=prime[i];while(m%prime[i]==0){cnt2[top]++;m/=prime[i];}top++;}if(m==1) break;}if(m!=1){cnt1[top]=m;cnt2[top]++;top++;}memset(tmp,0,sizeof(tmp));for(int i=1;i<n-1;i++){deal(n-i,1);deal(i,-1);if(ok()){ans[num++]=i+1;}} // if(first) first=0; // else printf("\n");printf("%d\n",num);if(num==0){printf("\n");continue;}for(int i=0;i<num-1;i++){printf("%d ",ans[i]);}printf("%d\n",ans[num-1]);}return 0; }總結
- 上一篇: UVa10791
- 下一篇: 成都大熊猫繁育基地下雨能去吗