A
#include <bits/stdc++.h>
using namespace std;
const int N = 105;
int a[N],n,t;
signed main() {
ios::sync_with_stdio(false);
cin>>t;
while(t--) {
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
if(n==1 && a[1]%2) {
cout<<-1<<endl;
}
else if(n==1) {
cout<<1<<endl<<1<<endl;
}
else if(a[1]%2==0) {
cout<<1<<endl<<1<<endl;
}
else if(a[2]%2==0) {
cout<<1<<endl<<2<<endl;
}
else cout<<2<<endl<<"1 2"<<endl;
}
}
B
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 100005;
int n,m,a[N],b[N],c[N],d[N],k,ans;
void gen(int *x,int l) {
for(int i=1;i<=l;i++) x[i]+=l+1-i;
}
signed main() {
ios::sync_with_stdio(false);
cin>>n>>m>>k;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=m;i++) cin>>b[i];
int last=1;
for(int i=1;i<=n+1;i++) {
if(a[i] && !a[i-1]) last=i;
if(!a[i] && a[i-1]) {
gen(c,i-last);
}
}
last=1;
for(int i=1;i<=m+1;i++) {
if(b[i] && !b[i-1]) last=i;
if(!b[i] && b[i-1]) {
gen(d,i-last);
}
}
for(int i=1;i*i<=k;i++) if(k%i==0) {
int tmp=0;
int x=i,y=k/i;
if(y<N) {
tmp=c[x]*d[y];
if(x!=y) tmp+=c[y]*d[x];
}
ans+=tmp;
}
cout<<ans;
}
C
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1000005;
int n;
char a[N];
signed main() {
ios::sync_with_stdio(false);
cin>>n;
cin>>(a+1);
int sum1=0,sum2=0;
for(int i=1;i<=n;i++) {
if(a[i]=='(') ++sum1;
else ++sum2;
}
if(sum1!=sum2) {
puts("-1");
exit(0);
}
int sum=0;
int last=0;
int ans=0;
for(int i=1;i<=n;i++) {
if(a[i]=='(') ++sum;
else --sum;
if(sum<0 && last==0) {
last=i;
}
if(sum==0 && last) {
ans+=i-last+1;
last=0;
}
}
cout<<ans;
}
D
求每对数代数和的异或和,(n leq 4 imes 10^5)
按位拆分后计算,转化为求和的第 (k) 位是 (1) 的数对的个数
考虑将所有数 (mod 2^{k+1}),那么数对和在 ([2^k,2^{k+1})) 或 ([2^k+2^{k+1},2^{k+2})) 中的有贡献
排序后二分即可
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1000005;
const int M = 28;
#define pw(x) (1<<(x))
int n,a[N],b[N],ans,tans;
signed main() {
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int k=0;k<M;k++) {
for(int i=1;i<=n;i++) {
b[i]=a[i]%pw(k+1);
}
tans=0;
sort(b+1,b+n+1);
for(int i=1;i<=n;i++) {
tans+=lower_bound(b+1,b+n+1,pw(k+1)-b[i])-lower_bound(b+1,b+n+1,pw(k+0)-b[i]);
tans+=lower_bound(b+1,b+n+1,pw(k+2)-b[i])-lower_bound(b+1,b+n+1,pw(k+1)+pw(k+0)-b[i]);
}
for(int i=1;i<=n;i++) if((a[i]*2)&pw(k)) --tans;
tans/=2;
if(tans&1) ans+=pw(k);
}
cout<<ans;
}
E
给定一张点数为 (2N) 的二分图,其中右侧的第 (i) 个点有点权为 (c_i) 的权值,令 (S) 表示左侧的一个非空点集合,设 (f(S)) 表示右侧点中至少与 (S) 中一个点相连的点权和,求出对所有非空集合 (S),(f(S)) 的 (gcd) 是多少
核心依据是 (gcd(a+b,a,b)=gcd(a,b))
对于右侧的每一个点 (i),设与它相连的左侧点集合为 (g(i))
如果 (g(i)=g(j)),我们就可以把 (i,j) 合并,权值求和,这个过程可以用 DSU 维护
注意!如果某个点没有相连则需要跳过它
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 500005;
const int mod = 114514191;
const int mod2 = 998244353;
struct hsh {
int a=0,c=0;
void clear() {a=0;c=0;}
void insert(int x) {
int y=x%mod2*x%mod2;
x=x%mod*x%mod*x%mod;
a+=x; a%=mod;
c+=y; c%=mod2;
}
bool operator == (const hsh &b) const {
return a==b.a && c==b.c;
}
} h[N];
int t,n,m,c[N],f[N];
int find(int p) {
return f[p]==p ? p : f[p]=find(f[p]);
}
void merge(int p,int q) {
p=find(p); q=find(q);
if(p-q) f[p]=q;
}
map<int,int> mp;
void read(int &x) {
cin>>x;
}
void print(int x) {
cout<<x<<endl;
}
signed main() {
ios::sync_with_stdio(false);
read(t);
while(t--) {
read(n); read(m);
for(int i=1;i<=n;i++) cin>>c[i];
for(int i=1;i<=n;i++) h[i].clear(), f[i]=i;
for(int i=1;i<=m;i++) {
int t1,t2;
read(t1); read(t2);
h[t2].insert(t1);
}
for(int i=1;i<=n;i++) {
if(h[i].a==0 && h[i].c==0) c[i]=0;
}
mp.clear();
for(int i=1;i<=n;i++) {
mp[h[i].a+h[i].c]=i;
}
for(int i=1;i<=n;i++) {
merge(i,mp[h[i].a+h[i].c]);
}
for(int i=1;i<=n;i++) {
if(i!=f[i]) c[f[i]]+=c[i];
}
int ans=0;
for(int i=1;i<=n;i++) {
if(i==f[i]) ans=__gcd(ans,c[i]);
}
print(ans);
}
}