链接:
2681. 英雄的力量
题意:
对于一个序列可以得到一个值max^2 * min
,求一个数组的所有子序列数值和
解:
快速幂和慢速乘+暴力 TLE(2558 / 2584)
首先对于这个数组来说,求值只依靠序列的最大值和最小值,并且所有子序列都要求,所以我们先将数组排序
对于每次遍历到的数字nums[i]
都有一个nums[i]^3
加入到ans里(表示子集[i,i]
,子集[l,r]
表示以L为最小值,R为最大值的子集)
同时我们还要计算[0,i],[1,i]......[i-1,i]
,我们可以发现子集[l,r]
的值的和是nums[r]^2 * nums[l] * 2^r-l-1
,因为l和r之间有r-l-1
个数字,每个数字都有选与不选两种状态且不影响子集[l,r]
的值,那我们可以发现每当R右移1,它所需要乘上的每个nums[l]
就要翻一倍,所以我们使用一个变量来累积他所需要乘的数值
例如nums[1],nums[2],nums[3]
对于nums[1]
我们只需要求nums[1]^3
对于nums[2]
需要nums[2]^3 + nums[2]^2 * nums[1] * 1
对于nums[3]
需要nums[3]^3 + nums[3]^2 * nums[2] *1 +nums[3]^2 *nums[1] * 2
这个nums[3]
除了nums[3]^3
,剩下的nums[3]^2 * nums[2] *1 +nums[3]^2 *nums[1] * 2
可以转化为(nums[3]^2)*(nums[2]+ 2* nums[1])
。
以此类推下一个就是(nums[4]^2)*(nums[3]+ 2* nums[2]+ 4* nums[1])
。
实际代码:
#include<bits/stdc++.h>
using namespace std;
constexpr static long long Mod=1E9+7;
long long msc(long long base,long long up)
{//cout<<base<<"up"<<up<<endl;long long ret=0;while(up){if(up&1) ret+=base;base+=base;base%=Mod;ret%=Mod;up>>=1;}return ret;
}
long long msm(long long base,long long up)
{//cout<<base<<"msmup"<<up<<endl;long long ret=1;while(up){if(up&1) ret*=base;base=msc(base,base);base%=Mod;ret%=Mod;up>>=1;}return ret;
}
int sumOfPower(vector<int>& nums)
{sort(nums.begin(),nums.end());long long ans=0,after=0;int lg=nums.size();for(int i=0;i<lg;i++){ans+=msm(nums[i],3);ans+=msm(nums[i],2)*after;after*=2;after+=nums[i];after%=Mod;ans%=Mod;}return ans;
}
/*
int sumOfPower(vector<int>& nums)
{sort(nums.begin(),nums.end());long long ans=0;int lg=nums.size();for(int i=0;i<lg;i++){for(int j=i;j<lg;j++){//cout<<"i:"<<i<<" "<<"j:"<<j<<endl;if(i==j) ans+=msm(nums[i],3);else{ans+=msc(msc(msm(nums[j],2),nums[i]),msm(2,j-i-1));}ans%=Mod;}}return ans;
}*/
int main()
{vector<int> nums;int num;while(cin>>num)nums.push_back(num);int ans=sumOfPower(nums);cout<<ans<<endl;return 0;
}
限制:
1 <= nums.length <= 105
1 <= nums[i] <= 109