链接:
题意:
对于一个序列可以得到一个值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