HDU 5288 OO’s Sequence (數論)

題意:定義一個函數f(l,r) = i的個數使得在區間[l,r]中不存在a[i]%a[j]=0。∑i=1..n∑j=i..n  f(i,j) mod (10^9+7)。

解析:通過枚舉因子,從前到後再從後到前求出能包含i的區間的左右端點的邊界,即可。

[code]:

#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;
typedef long long LL;
const int maxn = 1e5+5;
const LL MOD = 1e9+7;

int n,a[maxn],b[maxn];
int l[maxn],r[maxn];

void sol(){
    int i,j;
    memset(b,0,sizeof(b));
    for(i = 1;i <= n;i++){
        l[i] = 0;
        for(j=1;j*j<=a[i];j++){
            if(a[i]%j) continue;
            l[i] = max(l[i],max(b[a[i]/j],b[j]));
        }
        b[a[i]] = i;
    }
    memset(b,63,sizeof(b));
    for(i = n;i >= 1;i--){
        r[i] = n+1;
        for(j=1;j*j<=a[i];j++){
            if(a[i]%j) continue;
            r[i] = min(r[i],min(b[a[i]/j],b[j]));
        }
        b[a[i]] = i;
    }
    LL res = 0;
    for(i = 1;i <= n;i++){
        res += (1LL*i-1LL*l[i])*(1LL*r[i]-1LL*i);
        res %= MOD;
    }
    printf("%lld\n",(res+MOD)%MOD);
}

int main(){
    int i,j;
    while(~scanf("%d",&n)){
        for(i = 1;i <= n;i++) scanf("%d",&a[i]);
        sol();
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章