标签:ret number 从右到左 order cin osi typedef family sans
Description
Input
Output
Sample Input
5 1 2 3 4 5
Sample Output
23
。
。比方5 5 2 3 3 4 3 2 5 5。那么对于4来说,我们找到左右两个因子2之后,就能够发现从5開始和结束的子区间都不会算到4。由于有2在那里杵着。
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; const int MAXN = 1e5 + 10; const int MAXM = 1e4 + 10; const int INF = 0x3f3f3f3f; const int MOD = 1e9 + 7; int nums[MAXN]; //序列中的数 int lb[MAXN], rb[MAXN]; //序列中的数左右离他近期的因子的位置 int latest[MAXM];//某个数字最后出现的位置 int main() { int n; while(scanf( "%d", &n ) == 1) { memset( lb, 0, sizeof lb ); memset( rb, INF, sizeof rb ); //reset for(int i = 1; i <= n; i++) { scanf( "%d", &nums[i] ); }//input for(int i = 0; i < MAXM; i++) latest[i] = 0; for(int i = 1; i <= n; i++) { for(int j = 1; j <= sqrt( nums[i] ); j++) {//遍历每一个因子 if(nums[i] % j == 0) { lb[i] = max( lb[i], latest[j] ); lb[i] = max( lb[i], latest[nums[i] / j] ); } } latest[nums[i]] = i; //更新位置。注意要遍历后更新,由于本身也是自己的因子 }// tackle 1 for(int i = 0; i < MAXM; i++) latest[i] = n + 1; for(int i = n; i >= 1; i--) { for(int j = 1; j <= sqrt( nums[i] ); j++) { if(nums[i] % j == 0) { rb[i] = min( rb[i], latest[j] ); rb[i] = min( rb[i], latest[nums[i] / j] ); } } latest[nums[i]] = i; }// tackle 2 同理 ll ans = 0; for(int i = 1; i <= n; i++) { ans = (ans + (i - lb[i])*(rb[i] - i)) % MOD; //统计序列中每一个数被统计的次数。能够理解为范围内左边选一个数的选法*右边选一个数的选法。 } printf( "%lld\n", ans ); } return 0; }
解题报告 之 HDU5288 OO' s Sequence
标签:ret number 从右到左 order cin osi typedef family sans
原文地址:http://www.cnblogs.com/mthoutai/p/6823327.html