【思路题】【多校第一场】【1001.OO’s Sequence】
题目大意:
给你一个序列A,f(l,r) 表示 在[l,r]中 的Ai 对于每一个数Aj 都有 Ai%Aj!=0 的数目( i!=j )
卡了一段时间。。。。。
题解
简单题 定义两个数组L[i],R[i],表示第i数左侧和右侧最接近它且值是A[i]因子的数的位置,那么第i个数贡献的答案就是(R[i]-i ) * (i-L[i])
#include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <ctime> #include <algorithm> #include <iostream> #include <sstream> #include <string> #define oo 0x13131313 const long long MOD=(1e9)+7; using namespace std; long long A[100005]; long long Q[100005]; long long H[100005]; long long C[100005]; long long P[100005]; long long pos[10005]; long long n; void input() { memset(Q,0,sizeof(Q)); memset(H,0,sizeof(H)); memset(A,0,sizeof(A)); for(int i=1;i<=n;i++) scanf("%d",&A[i]); } void YCL() { for(int i=1;i<=100000;i++) { P[i]=(P[i-1]+i)%MOD; C[i]=(C[i-1]+P[i])%MOD; } } void step1() { memset(pos,0,sizeof(pos)); for(int i=1;i<=n;i++) { long long MAX=0; long long t=sqrt(A[i]); for(int j=1;j<=t;j++) { if(A[i]%j==0) { MAX=max(MAX,pos[j]); MAX=max(MAX,pos[A[i]/j]); } } Q[i]=MAX; pos[A[i]]=i; } for(int i=0;i<=10000;i++) pos[i]=n+1; for(int i=n;i>=1;i--) { long long MIN=n+1; long long t=sqrt(A[i]); for(int j=1;j<=t;j++) { if(A[i]%j==0) { MIN=min(MIN,pos[j]); MIN=min(MIN,pos[A[i]/j]); } } H[i]=MIN; pos[A[i]]=i; } } void solve() { long long ans=0; for(int i=1;i<=n;i++) { long long len1=H[i]-Q[i]; long long len2=i-Q[i]; long long len3=H[i]-i; ans=(ans+(len1*(len1+1)/2)-(len2*(len2+1)/2)-(len3*(len3+1)/2))%MOD; } cout<<ans<<endl; } int main() { // freopen("a.in","r",stdin); YCL(); while(cin>>n) { input(); step1(); solve(); } }