大餐 是指 恰好包含两道不同餐品 的一餐,其美味程度之和等于 2 的幂。
你可以搭配 任意 两道餐品做一顿大餐。
给你一个整数数组 deliciousness ,其中 deliciousness[i] 是第 i 道餐品的美味程度,返回你可以用数组中的餐品做出的不同 大餐 的数量。结果需要对 10e9 + 7 取余。
注意,只要餐品下标不同,就可以认为是不同的餐品,即便它们的美味程度相同。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/count-good-meals
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
1、想法:
最初:暴力求解,整个的复杂度为O(n^2)
优化:奇数,偶数分开各自计算,复杂度只减少一半
最终:使用二维数组,n*2维,将重复的数排除,这样既不用排序又不用分开奇数偶数。此时遍历一遍复杂度为O(n),在排除重复的数组后整个剩下的复杂度为O(1)-O(n)(全为相同的数,全为不同的数)。
2、问题
在测试时用int会导致溢出,使用long避免。
class Solution {
public:
int countPairs(vector<int>& deliciousness) {
// sort(deliciousness.begin(),deliciousness.end());
map<int,long>num;
int aa[22]={1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152};
vector<int>linshi;
int sum1=0,sum2=0;
int mod_=1e9+7;
for(int i=0;i<deliciousness.size();i++){
if(!(num.find(deliciousness[i])!=num.end())){
num[deliciousness[i]]=1;
linshi.push_back(deliciousness[i]);
}
else num[deliciousness[i]]= num[deliciousness[i]]+1;
}
// sort(linshi.begin(),linshi.end());
for(int i=0;i<linshi.size();i++){
for(int j=0;j<22;j++){
if(aa[j]-linshi[i]>=0&&num[aa[j]-linshi[i]]>0){
// printf("%lf %llf %llf\n",num[linshi[i]],num[linshi[i]]*(num[linshi[i]]-1),(num[linshi[i]]*(num[linshi[i]]-1))%mod_);
// printf("%d \n",(long)(num[linshi[i]]*(num[linshi[i]]-1))%mod_);
if(aa[j]==2*linshi[i]&&num[linshi[i]]>1)
sum1=(sum1+num[linshi[i]]*(num[linshi[i]]-1)/2)%mod_;
else if(aa[j]!=2*linshi[i])
sum2=(sum2+num[aa[j]-linshi[i]]*num[linshi[i]])%mod_;
// printf("%d-%d:%d %d:%d\n",aa[j],linshi[i],num[aa[j]-linshi[i]],linshi[i],num[linshi[i]]);
}
}
}
return (sum1+sum2/2)%mod_;
}
};