标签:
OO has got a array A of size n ,defined a function f(l,r) represent the number of i (l<=i<=r) , that there‘s no j(l<=j<=r,j<>i) satisfy ai mod aj=0,now OO want to know ∑i=1n∑j=inf(i,j) mod (109+7).
There are multiple test cases. Please process till EOF. In each test case: First line: an integer n(n<=10^5) indicating the size of array Second line:contain n numbers ai(0<ai<=10000)
For each tests: ouput a line contain a number ans.
5 1 2 3 4 5
23
题意:
本来的题意问 枚举所有i,j ,1<=i<=j<=n, 然后计算f(i,j)和是多少。
f(l,r)的值 是 输入的数组下标 l到r中有多少 数是无法被这个区间 任意一个数整除的。
做法:
转换种思想就是 某个数num[i],在多少个区间内 可以不被区间其他任何数整除。 答案加上区间个数。
所以 可以左右两边枚举过来。
以左边枚举过来为例:
把最近出现的数 记录下来,记录到 has数组。 如num[i] 记录成has[num[i]]=i
然后把每个数的因子枚举,判断最近左边出现因子在哪。 然后那个位子+1 就是左端点了。
在同样处理出右端点, 左右端点知道就很容易算出num[i]在多少区间内符合要求 加到ans里。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 #include<cmath> 7 #include<stdlib.h> 8 #include<map> 9 #include<vector> 10 using namespace std; 11 #define N 100006 12 #define M 10006 13 #define MOD 1000000007 14 int n; 15 int vis[M]; 16 int a[N]; 17 vector<int> G[M]; 18 int L[N]; 19 int R[N]; 20 void init(){ 21 for(int i=1;i<M;i++){ 22 for(int j=1;j<=i;j++){ 23 if(i%j==0){ 24 G[i].push_back(j); 25 } 26 } 27 } 28 } 29 int main() 30 { 31 init(); 32 while(scanf("%d",&n)==1){ 33 for(int i=1;i<=n;i++){ 34 scanf("%d",&a[i]); 35 } 36 memset(vis,0,sizeof(vis)); 37 memset(L,-1,sizeof(L)); 38 memset(R,-1,sizeof(R)); 39 for(int i=1;i<=n;i++){ 40 for(int j=0;j<G[a[i]].size();j++){ 41 int tmp=G[a[i]][j]; 42 if(vis[tmp]){ 43 if(a[i]%tmp==0){ 44 if(L[i]!=-1){ 45 L[i]=max(L[i],vis[tmp]+1); 46 } 47 else{ 48 L[i]=vis[tmp]+1; 49 } 50 } 51 52 } 53 } 54 vis[a[i]]=i; 55 } 56 memset(vis,0,sizeof(vis)); 57 for(int i=n;i>=1;i--){ 58 for(int j=0;j<G[a[i]].size();j++){ 59 int tmp=G[a[i]][j]; 60 if(vis[tmp]){ 61 if(a[i]%tmp==0){ 62 if(R[i]!=-1){ 63 R[i]=min(R[i],vis[tmp]-1); 64 } 65 else{ 66 R[i]=vis[tmp]-1; 67 } 68 } 69 70 } 71 } 72 vis[a[i]]=i; 73 } 74 int ans=0; 75 for(int i=1;i<=n;i++){ 76 if(L[i]==-1){ 77 L[i]=1; 78 } 79 if(R[i]==-1){ 80 R[i]=n; 81 } 82 } 83 for(int i=1;i<=n;i++){ 84 ans=(ans+(i-L[i]+1)*(R[i]-i+1))%MOD; 85 } 86 printf("%d\n",ans); 87 } 88 return 0; 89 }
标签:
原文地址:http://www.cnblogs.com/UniqueColor/p/4799363.html