先从小到大排序
对每个nums[i],sum += 1,表示自己除自己为1
一、
令p = i + 1,q = 第一个大于等于nums[i]的数的下标,则q - p为与nums[i]相等的数的个数,
sum += (q - p)* 2,因为我们只考虑 5 / 2,而不用考虑2 / 5,但若有两个5,则必须考虑$5_1 / 5_2,5_2 / 5_1$
所以要*2
二、
之后令q = p,令ans = 1,每次令q = 第一个大于等于nums[i] * (ans + 1)的数的下标,则(q - p)即为有(q - p)个数除nums[i] = ans
sum += (q - p)* ans;
ans++;
直到ans * nums[i] 大于 最大值,则i++,继续下一个nums
每次记录一中的值和二中的值,如果第i + 1个数与第i个相同,则可以重复使用
class Solution { public: int vis[100010]; bool vis1[100010]; set<int> ss; int mod = 1e9 + 7; int sumOfFlooredPairs(vector<int>& nums) { memset(vis, 0, sizeof(vis)); memset(vis1, 0, sizeof(vis1)); // vector<int> NUM; int n = nums.size(); int max_v = -1; for(int i = 0; i < n; i++) { vis[nums[i]]++; max_v = max(max_v, nums[i]); // ss.insert(nums[i]); } sort(nums.begin(), nums.end()); int sum = 0, cnt = 0, pre_same, pre_nosame; for(int i = 0; i < n; i++) { sum = (sum + 1) % mod; if(i > 0 && nums[i] == nums[i - 1]) { pre_same--; sum = (sum + pre_same * 2 % mod) % mod; sum = (sum + pre_nosame) % mod; continue; } pre_nosame = 0; int ans = 1, p = i + 1, q; q = upper_bound(nums.begin(), nums.end(), nums[i]) - nums.begin(); sum = (sum + (q - p) * 2 % mod) % mod; pre_same = q - p; p = q; while(i < n - 1 && (nums[i]) * ans <= max_v) { q = lower_bound(nums.begin(), nums.end(), nums[i] * (ans + 1)) - nums.begin(); sum = (sum + (((q - p) * ans) % mod) ) % mod; pre_nosame = (pre_nosame + (q - p) * ans % mod) % mod; ans++; p = q; } } return sum; } };