[USACO08DEC]拍頭Patting Heads 題解
阿新 • • 發佈:2018-11-10
題目連結:智慧手機
題意:N個數字a[i],求N個數字中除去第i個數字,有多少數字為a[i]的因子?
資料範圍:a[i],n<=1e6.
我這裡介紹兩種方法:
1.列舉x=1--->n,再sqrt(x)的去判斷x的因子個數。時間複雜度O(n*sqrt(n)).
程式碼:
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #define ll long long int #defineR register using namespace std; const int N=1e6+10; int n,a[N],ans[N],num[N],Max; int main(){ memset(ans,-1,sizeof(ans)); scanf("%d",&n); for(R int i=1;i<=n;++i){ scanf("%d",&a[i]); Max=max(Max,a[i]); ++num[a[i]]; } for(R int i=1;i<=n;++i){ Rint k=a[i]; for(R int x=1;x<=sqrt(k);++x) if(k%x==0){ R int y=k/x; ans[i]+=num[x]+num[y]; if(x*x==k)ans[i]-=num[x]; } } for(R int i=1;i<=n;++i) printf("%d\n",ans[i]); return 0; } // O(n)列舉每個數字 // O(sqrt(n))列舉 當前數字的 因子
2.列舉因數,a[i]的因數最大值為max(a[i])(i=1--->n)。再去列舉因數的倍數,最大值為Max/i。已知調和級數可以證明時間複雜度為O(n*log2(n)).
程式碼:
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #define ll long long int #define R register using namespace std; const int N=1e6+5; int n,a[N],num[N],ans[N],Max; int main(){ memset(ans,-1,sizeof(ans)); scanf("%d",&n); for(R int i=1;i<=n;i++){ scanf("%d",&a[i]); Max=max(Max,a[i]); num[a[i]]++; } for(R int i=1;i<=Max;i++){//列舉因數 if(!num[i])continue; for(R int j=1;j<=Max/i;j++)//列舉因數的倍數 ans[i*j]+=num[i]; } for(R int i=1;i<=n;i++) printf("%d\n",ans[a[i]]); return 0; } // 列舉 數字 // 用 每個數字 去更新 它的倍數.
因為要刪去自己整除自己的情況,所以memset(ans,-1,sizeof(ans)).