不会的可以去看看裴蜀定理,经常用到,见过就会了
#include<bits/stdc++.h>
#define int long long
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const long long N=1e6+10,mod=998244353,INF=1e15;
ll n,m,k,a,b,c,d;
bool st[N];
void solve()
{
cin>>n>>m>>a>>b>>c>>d;
int x=__gcd(a,b),y=__gcd(c,d);
if(m%x==0&&n%y==0)cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
signed main()
{
cin.tie(0), cout.tie(0), ios::sync_with_stdio(false);
int T;cin>>T;
while(T--)solve();
return 0;
}
按每一位考虑,假设当前考虑第i位,将所有在第i位上不为0的数用带权并查集合并就好了
#include<bits/stdc++.h>
#define int long long
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const long long N=1e6+10,mod=998244353,INF=1e15;
ll n,m,k,a[N],f[N],s[N];
bool st[N];
int find(int x)
{
if(x!=f[x])f[x]=find(f[x]);
return f[x];
}
void solve()
{
cin>>n;
for(int i=1;i<=n;i++)f[i]=i,s[i]=1;
for(int i=1;i<=n;i++)cin>>a[i];
for(int j=0;j<=60;j++)
{
int lst=-1;
for(int i=1;i<=n;i++)
{
if(a[i]>>j&1)
{
if(lst!=-1)
{
int fa=find(lst),fb=find(i);
if(fa==fb)continue;
s[fa]+=s[fb];
f[fb]=fa;
}
lst=i;
}
}
}
int ans=0;
for(int i=1;i<=n;i++)ans=max(ans,s[find(i)]);
cout<<ans<<endl;
}
signed main()
{
cin.tie(0), cout.tie(0), ios::sync_with_stdio(false);
int T;cin>>T;
while(T--)solve();
return 0;
}
线段树简单题,线段树里面维护答案,还有ll(区间左端有多少个连续的0),rr(区间右端有几个连续的0),具体怎么合并看代码,学过线段树就非常好懂
#include<bits/stdc++.h>
#define int long long
using namespace std;
const long long N=2e5+10;
int n,m;
string s;
struct node
{
int l,r,ans,ll,rr;
}t[4*N];
void pushup(node &u,node L,node R)
{
int lenl=L.r-L.l+1,lenr=R.r-R.l+1;
u.l=L.l,u.r=R.r;
u.ans=L.ans+R.ans+lenl*lenr-L.rr*R.ll;
u.ll=L.ll+R.ll*(L.ll==lenl);
u.rr=R.rr+L.rr*(R.rr==lenr);
}
void build(int u,int l,int r)
{
t[u]={l,r};
if(l==r)
{
int x=(s[l]=='1');
t[u]={l,r,x,1-x,1-x};return;
}
int mid=(l+r)/2;
build(u<<1,l,mid),build(u<<1|1,mid+1,r);
pushup(t[u],t[u<<1],t[u<<1|1]);
}
node query(int u,int l,int r)
{
if(l<=t[u].l&&t[u].r<=r)return t[u];
else{
int mid=(t[u].l+t[u].r)/2;
if(r<=mid)return query(u<<1,l,r);
if(l>mid)return query(u<<1|1,l,r);
node ll,rr,res;
ll=query(u<<1,l,r);
rr=query(u<<1|1,l,r);
pushup(res,ll,rr);
return res;
}
}
signed main()
{
cin>>n;
cin>>s;
s=" "+s;
cin>>m;
build(1,1,n);
for(int i=1;i<=m;i++)
{
int l,r;cin>>l>>r;
node res=query(1,l,r);
cout<<res.ans<<endl;
}
return 0;
}
考虑节点u,首先看它自己是不是关键节点,如果是那么cnt[u]初值为1,否则为0,因为他可以选自己,记dp[u]为子树u里面有多少个关键节点,那么cnt[u],还要加上他的所以儿子v的dp[v]两两相乘,这个也非常好算,直接边算dp边计数就可以了,cnt[u]+=2*dp[u]*dp[v],dp[u]+=dp[v],表示当前儿子于前面遍历到的所有节点的方案,再把这个儿子加到u里面,记得乘个2,这样可以保证不重不漏
#include<bits/stdc++.h>
#define int long long
using namespace std;
const long long N=1e5+10;
int n,m,k,a[N],cnt[N],dp[N];
vector<int>p[N];
void dfs(int u,int fa)
{
cnt[u]=dp[u];
for(int x:p[u])
{
if(x==fa)continue;
dfs(x,u);
cnt[u]+=2*dp[u]*dp[x];
dp[u]+=dp[x];
}
}
signed main()
{
cin>>n;
for(int i=1;i<n;i++)
{
int u,v;cin>>u>>v;
p[u].push_back(v);
p[v].push_back(u);
}
cin>>m;
for(int i=1;i<=m;i++)
{
int x;cin>>x;
dp[x]=1;
}
dfs(1,0);
for(int i=1;i<=n;i++)cout<<cnt[i]<<' ';
return 0;
}
1864

被折叠的 条评论
为什么被折叠?



