B.Count Subrectangles
思路:
存因子到数组中
遍历因子算满足该因子个数的行和另一因子个数的列分别为多少相乘即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const double eps = 1e-8;
const int NINF = 0xc0c0c0c0;
const int INF = 0x3f3f3f3f;
const ll mod = 1e9 + 7;
const ll maxn = 1e5 + 5;
ll n,m,k;
int a[maxn];
int b[maxn];
int c[maxn];
int tot;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n>>m>>k;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=m;i++)
cin>>b[i];
for(int i=1;i*i<=k;i++){
if(k%i==0){
c[++tot]=i;
if(i==k/i) continue;
c[++tot]=k/i;
}
}
ll res=0;
for(ll i=1;i<=tot;i++){
int cnt=0;
ll x=0,y=0;
for(int j=1;j<=n;j++){
if(a[j]) cnt++;
else cnt=0;
if(cnt==c[i]) cnt--,x++;
}
cnt=0;
for(int j=1;j<=m;j++){
if(b[j]) cnt++;
else cnt=0;
if(cnt==k/c[i]) cnt--,y++;
}
res+=x*y;
}
cout<<res;
return 0;
}
D - Present
题意:
思路:
对每个二进制位单独考虑,若答案的第 i 位二进制位是 1,意味着有奇数对 (j,k) 满足 (a[j]+a[k]) 二进制第 i 位是 1.
高于 i 位的二进制位都不会对答案的第 i 位产生影响,那就把高于 i 位的先去掉,取模一下存入数组 b.
能令 i 位 1 为的 (b[j]+b[k])∈[2i,2i+1−1]∪[2i+1+2i,2i+2−1]
固定 b[j] 则 (b[j]+b[k])∈[2i−b[j],2i+1−1−b[j]]∪[2i+1+2i−b[j],2i+2−1−b[j]]
这里快速查找个数要用到二分查找
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const double eps = 1e-8;
const int NINF = 0xc0c0c0c0;
const int INF = 0x3f3f3f3f;
const ll maxn = 1e7 + 5;
int n,a[maxn],b[maxn],ans;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=0;i<26;i++){
int mod=1<<(i+1);//模数
for(int j=1;j<=n;j++) b[j]=a[j]%mod;//取模
int sum=0;
sort(b+1,b+n+1);
for(int j=1;j<=n;j++){//固定一个算另一个
int L,R;
L=lower_bound(b+1,b+1+n,(1<<i)-b[j])-b;
R=upper_bound(b+1,b+1+n,(1<<(i+1))-b[j]-1)-b;
sum+=(R-L);
L=lower_bound(b+1,b+1+n,(1<<i)+(1<<(i+1))-b[j])-b;
R=upper_bound(b+1,b+1+n,(1<<(i+2))-b[j]-1)-b;
sum+=(R-L);
if((b[j]+b[j])&(1<<i)) sum--;//细节:自己和自己相加的去掉 自己和自己最多只能在上式中出现一次
}
if((sum/2)&1) ans+=1<<i;//因为反复一对反复算了两次所以要除2再判断奇偶
}
cout<<ans;
return 0;
}