标签:
题意: 给你一个序列, 有一个函数 F(L,R) 其中 ai 均不能 被 aL … aR整除的 函数值是这个ai个数
思路 : 反过来求 满足这样的条件的 ai 的区间,然后求和
#include<iostream> #include<vector> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef __int64 LL; const int maxn = 100002; const LL MOD = 1e9 + 7; vector<int> Cnt[10005]; int Left[maxn], Right[maxn]; int Num[maxn],Vis[maxn]; int Scan() { int res = 0, ch, flag = 0; if((ch = getchar()) == ‘-‘) //判断正负 flag = 1; else if(ch >= ‘0‘ && ch <= ‘9‘) //得到完整的数 res = ch - ‘0‘; while((ch = getchar()) >= ‘0‘ && ch <= ‘9‘ ) res = res * 10 + ch - ‘0‘; return flag ? -res : res; } void Init() { for(int i = 1; i <= 10005; ++i) { for(int j = 1; j <= i; ++j) if(i % j == 0) Cnt[i].push_back(j); } } int main() { int n; Init(); while(scanf("%d",&n) != EOF) { for(int i = 0; i < n; ++i) Num[i] = Scan(); memset(Left,-1,sizeof(Left)); memset(Right,-1,sizeof(Right)); memset(Vis,-1,sizeof(Vis)); //GET LEFT for(int i = 0; i < n; ++i) { for(int j = 0; j < Cnt[Num[i]].size(); ++j) { int tmp = Cnt[Num[i]][j]; if(Vis[tmp] != -1 && Num[i] % tmp == 0) { if(Left[i] == -1) Left[i] = Vis[tmp] + 1; else Left[i] = max(Left[i],Vis[tmp]+1); } } Vis[Num[i]] = i; } //GET RIGHT memset(Vis,-1,sizeof(Vis)); for(int i = n-1; i >= 0; --i) { for(int j = 0; j < Cnt[Num[i]].size(); ++j) { int tmp = Cnt[Num[i]][j]; if(Vis[tmp] != -1 && Num[i] % tmp == 0) { if(Right[i] == -1) Right[i] = Vis[tmp] - 1; else Right[i] = min(Right[i],Vis[tmp]-1); } } Vis[Num[i]] = i; } for(int i = 0; i < n; ++i) { if(Left[i] == -1) Left[i] = 0; if(Right[i] == -1) Right[i] = n-1; } LL ans = 0; for(LL i = 0; i < n; ++i) { LL L = i - Left[i] + 1; LL R = Right[i] - i + 1; ans = (ans + L * R) % MOD; } printf("%I64d\n",ans); } }
标签:
原文地址:http://www.cnblogs.com/aoxuets/p/4700179.html