第一題
思路:簡單二分查詢(錯因二分查詢不熟)
程式碼如下
點選檢視程式碼
#include<iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
long long a[1000010];
unordered_map<long long,long long>mp;
bool cmp(long long a,long long b){
return a<b;
}
int main(){
long long n,q,a1,x,y;
cin>>n>>q;
for(int i=0;i<n;i++){
scanf("%lld",&a1);
a[i]=a1*a1;
}
sort(a,a+n,cmp);
for(int i=0;i<q;i++){
scanf("%lld%lld",&x,&y);
long long num=x*x+y*y;
int ans=upper_bound(a,a+n,num)-a;
printf("%d\n",ans);
}
return 0;
}
二分查詢的分類
1. 查詢比剛好標準數大或小的數。
2. 查詢標準數的下標,不存在就返回-1。
對於第一類查詢,只需要upper_bound(a,a+n,x)-a和lower_bound(a,a+n,x)-a就可以判斷
或者手寫
-
主要注意兩點if(a【mid】<=k)判斷有沒有可能是答案,有可能則l=mid沒可能則l=mid+1;
-
判斷是(l+r+1)>>1是(l+r)>>1,就是將ans=l帶入第一個是mid恆為l一直執行,第二個mid=r終止,同理ans=r時,選第一個。
第二類查詢就直接手寫
while(l < r){
long long mid = (l + r + 1) >> 1; //因為l=mid,所以在折半取值時,mid應優先取ceil((l+r)/2),避免死迴圈
if(nums[mid] <= target){
l = mid; //nums[mid]可能為答案
}else{
r = mid - 1;//nums[mid]肯定不是答案了,就將該mid踢出答案所在的[l,r]區間內
}
}
if(nums[l] == target) return l;
return -1;
講解連線 https://www.zhihu.com/question/268507619/answer/2333102984
第二題 位運算加思維
思路
1. 將a1|a2|a3|a4|a5|a6....和b1|b2|b3|b4|b5......看成一個二進位制的字串(010101101001100110)
2. 先考慮相等的情況,考慮第i位的二進位制數決定a1...>b1...
得出以下結論:
- 前i-1的二進位制相等,a的前n個數的前i-1位可以亂取,b的前n-1個數前i-1位也可以亂取,因為b的第n個數的前i-1異或可為任意值,所以sum1=(2(i-1)n * (2(i-1))n-1=2**((i-1)(2n-1))
- a的第i位為1且b的第i位為0 只要a的n數第i位中有一個不為0的,a的第i位不為0,b的前n-1個數的第i位任意,第n個數的第i位確定 所以sum2=2(n)-1 * 2(n-1)
- a,b的m-i位可為任意值 sum=2(n(m-i)) * 2(n(m-i))=2**(2n(m-i))
3. 最後考慮a=b的情況 a可任取,b前n-1個數任取 sum3=2(m(n)) * 2(m(n-1))=2**(m(2n-1))
4. 列舉i的每一位即可
程式碼
點選檢視程式碼
#include<bits/stdc++.h>
#define ll long long
#define cin(x) scanf("%d",&x)
#define cout(x) printf("%d",x)
#define cinll(x) scanf("%lld",&x)
#define coutll(x) printf("%lld",x)
#define pb(x) push_back(x)
using namespace std;
const int mod=1e9+7;
int pow(int x,int y){
int res=1;
for(;y;x=1ll*x*x%mod,y>>=1){
if(y&1)res=1ll*res*x%mod;
}
return res;
}
int main(){
int n,m;
ll ans=0;
cin>>n>>m;
for(int i=1;i<=m;i++){
ans = (ans + 1ll *pow(pow(2, i - 1), 2 *n -1) *(pow(2, n) - 1) % mod*pow(2, n -1) % mod *pow(pow(2, m - i), 2 * n)) % mod;
}
ans=(ans+pow(pow(2,m),2*n-1))%mod;
cout<<ans;
return 0;
}
注意
long long 不可以直接%,所以要先開成int型的陣列,再用1ll*ans,可以變成ll型且可以求模