1. 程式人生 > >[USACO08DEC]拍頭Patting Heads 題解

[USACO08DEC]拍頭Patting Heads 題解

題目連結:智慧手機

題意: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
#define
R 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){ R
int 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)).