文章目录

  • 0x33 同余
    • 同余类+剩余系+费马小定理+欧拉定理及推论
    • 最幸运的数字
      • 题解
      • 这次的代码很多东西:欧拉函数快速求解,gcd,快速乘,各种定理,建议当模板背
        • 10LL 转换成长整型
        • 快速乘+快速幂(取模)模板
        • 技巧:试除法可以一半一半求,减少遍历次数,两半都用稠密的一半遍历(因子是成对的)
    • 扩展欧几里得算法
      • ax+by=gcd(a,b)存在至少一组整数解xy
    • 乘法逆元
    • sumdiv
      • 新的逆元做法,下次再做吧
    • 线性同余方程
    • 同余方程
      • 就是exgcd的模板题
    • 中国剩余定理
    • 表达整数的奇怪方式
      • 思路
      • 看题解更好些
        • 没法一口气求解,只能一个一个往上增加
  • 0x41并查集
      • 这个东西很适合搞图的连通性==“擅长维护传递性”
    • 模板
    • 程序自动分析
      • 标准的并查集题
        • 不想离散化,所以map版并查集,但会有一组TLE
        • 在map基础上,把相等的和不等的分开存储,空间*2,时间/2,牛客能过了,acwing多过了几条数据,但还是7组
        • 我透了,改个unordered_map就能过,或者开O2(O2不能过)
      • 2021.3.7复习解法(能过前九个):有个很不错的结构体写法
    • supermarket
    • 扩展域与边带权的并查集
    • 银河英雄传说
      • 虽然dx的变化有一半是写在get里面的,但如果不merge,fa[x]指向的是当前根节点,根节点dx为0,dx+=d【fa【x】】不会发生改变-----------每一次merge,对每个节点只+1次,且不会影响其他同集合的节点
      • 带图的题解
        • 另外有的标准size是关键字,不能用,不过编译
      • 银河英雄传说---边权集2021.3.8复习---有注释!
      • 2021.4.17研究出来的模板
    • 奇偶游戏
      • 边权集解法
        • 先将正常数组改成前缀和,变成两个点的奇偶性,这样“权”就可以变成d[x](x与根之间),奇偶性的话,就用抑或来计算,如果已经有了,那么通过dx来计算x与y之间奇偶性,如果没有联通,那么要通过已知x与y之间奇偶性,倒推两个根节点之间的奇偶性,合并,另外数很稀疏,考虑离散化
        • acwing秦淮河大佬的复现书上代码,思路很棒
      • 扩展域解法(这个很简单,维护两个域,互相也是联通的,不用算权值了)
      • 扩展域解法1.不要忘了初始化2.不要忘了-1 3.扩展域一定要放一个数组里 ------------2021.3.8复习
    • 食物链
      • 拓展域
        • 三个域
        • 2021.3.8复习:这里的捕食域,同类域,天敌域,通过三个域表达出了方向关系(X被Y捕食,Y是X的天敌):通过X的Xself 与 Y的 Yeat 联通
      • 边带权
        • 把吃,被吃,同类设为 1,2,0,每次维护就好

0x33 同余

同余类+剩余系+费马小定理+欧拉定理及推论



最幸运的数字

现在给定一个正整数L,请问至少多少个8连在一起组成的正整数
(即最小幸运数字)是L的倍数。
输入格式
输入包含多组测试用例。
每组测试用例占一行,包含一个整数L。
当输入用例L=0时,表示输入终止,该用例无需处理。
输出格式
每组测试用例输出结果占一行。
结果为“Case 1: ”+一个整数N,N代表满足条件的最小幸运数字的位数。
如果满足条件的幸运数字不存在,则N=0。
数据范围
1≤L≤2∗109
输入样例:
8
11
16
0
输出样例:
Case 1: 1
Case 2: 2

题解

这次的代码很多东西:欧拉函数快速求解,gcd,快速乘,各种定理,建议当模板背

10LL 转换成长整型

快速乘+快速幂(取模)模板

技巧:试除法可以一半一半求,减少遍历次数,两半都用稠密的一半遍历(因子是成对的)

#include"stdio.h"
#include"string.h"
#include"math.h"
#include"algorithm"
using namespace std;
typedef long long ll;ll L;ll gcd(ll a,ll b)
{if(a < b){ll t = a; a = b; b = t;}if(b == 0)return a;return gcd(b,a%b);
}
ll multi(ll a,ll b,ll mod)
{ll ans = 0;while(b){if(b & 1)ans = (ans + a) % mod;a = (a << 1) % mod;b = b >> 1;}return ans;
}
ll Ola(ll n)
{ll sum = n;for(int i = 2; i * i<= n; i ++){if(n % i)continue;sum = sum / i * (i - 1);while(n % i == 0)n = n / i;}if(n != 1)sum = sum / n * (n - 1);return sum;
}
int Quick(ll a,ll b,ll mod)
///a:10LL b:欧拉函数的因子,也就是次数 mod:9L/d
///这个就是快速幂,套了快乘的快速幂(因为mod可能很大)
{ll ans = 1; a %= mod;///a与n互质///a %= mod;不加也能过while(b){if(b & 1)ans = multi(ans,a,mod);b >>= 1;a = multi(a,a,mod);}if(ans == 1)return 1;return 0;
}
ll solve()
{ll g = L / gcd(L,8LL) * 9;///LL转换,g是9L除以dif(gcd(10LL,g) != 1) return 0;///a,n互质才有解ll sum = 1;ll num = Ola(g); ///把g的欧拉函数求出来///下面这个for是试除法求因子for(int i = 1; i * (ll)i <= num; i ++){if(num % i)  continue;///是因子就看看能不能余g///这个quick有个10LL的参数应该也是模板if(Quick(10LL,(ll)i,g) == 1)return i;}///依旧是试除法求因子,不过求的是大于根号的这一半(因为小于根号这一半较小嘛,更好求)ll m = sqrt(num);for(int i = m; i >= 1; i --){if(num % i == 0 && Quick(10LL,num / i,g) == 1)return num / i;}return 0;
}int main()
{int cnt = 1;while(~scanf("%lld",&L)){if(L == 0)  break;printf("Case %d: %lld\n",cnt ++,solve());}
}

扩展欧几里得算法

ax+by=gcd(a,b)存在至少一组整数解xy


乘法逆元


sumdiv

新的逆元做法,下次再做吧


线性同余方程


同余方程

求关于x的同余方程 ax ≡ 1(mod b) 的最小正整数解。输入格式
输入只有一行,包含两个正整数a,b,用一个空格隔开。输出格式
输出只有一行,包含一个正整数x,表示最小正整数解。输入数据保证一定有解。数据范围
2≤a,b≤2∗109
输入样例:
3 10
输出样例:
7

就是exgcd的模板题


#include <iostream>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;ll a,b,x,y;
ll exgcd(ll a,ll b,ll &x,ll &y)
{if(b==0){x=1,y=0;return a;}int d=exgcd(b,a%b,x,y);int z=x;x=y;y=z-y*(a/b);return d;
}
int main()
{cin>>a>>b;exgcd(a,b,x,y);cout<<(x%b+b)%b<<endl;return 0;
}

中国剩余定理


表达整数的奇怪方式

给定 2n 个整数a1,a2,…,an和m1,m2,…,mn,求一个最小的非负整数 x,满足∀i∈[1,n],x≡mi(mod ai)。输入格式
第1 行包含整数 n。第 2..n+1行:每 i+1 行包含两个整数ai和mi,数之间用空格隔开。输出格式
输出最小非负整数 x,如果 x 不存在,则输出 −1。
如果存在 x,则数据保证 x 一定在64位整数范围内。数据范围
1≤ai≤231−1,
0≤mi<ai
1≤n≤25
输入样例:
2
8 7
11 9
输出样例:
31

思路

看题解更好些

没法一口气求解,只能一个一个往上增加


#include <iostream>
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int n;
LL exgcd(LL a, LL b, LL &x, LL &y){///exgcdif(b == 0){x = 1, y = 0;return a;}LL d = exgcd(b, a % b, y, x);y -= a / b * x;return d;
}
LL inline mod(LL a, LL b){///防止负数的取模(最小化到0~b-1)return ((a % b) + b) % b;
}
int main()
{cin>>n;LL a1,m1;cin>>a1>>m1;for(int i=1;i<n;i++)///每输入一组都要合并{LL a2,m2,k1,k2;cin>>a2>>m2;LL d=exgcd(a1,-a2,k1,k2);///if((m2-m1)%d){///不是因数(不能整除),无解cout<<-1<<endl;return 0;}k1=mod(k1*(m2-m1)/d,abs(a2/d));m1=k1*a1+m1;///产生新的a1和m1a1=abs(a1/d*a2);}cout<<m1<<endl;return 0;
}

0x41并查集

这个东西很适合搞图的连通性==“擅长维护传递性”



模板

int fa[maxn];
void init()
{for(int i=0;i<maxn;i++){fa[maxn]=i;}
}
int get(int x)
{if(x==fa[x])return x;return fa[x]=get(fa[x]);
}
int mergefa(int x,int y)
{fa[get(x)]=get(y);
}

程序自动分析

标准的并查集题


不想离散化,所以map版并查集,但会有一组TLE

#include <iostream>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define maxn 1000005
map<int,int> fa;
int n;
int xi[maxn];
int yi[maxn];
int ei[maxn];
int get(int x)
{if(fa[x]==0||x==fa[x])///这个if应该是短路运算符///不过不加fa[x]==0||也行,已经把赋初值拆分了///map没赋过值的为0{fa[x]=x;///给没赋过值的准备的return x;}return fa[x]=get(fa[x]);
}
void mergefa(int x,int y)
{fa[get(x)]=get(y);
}
int main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int t;cin>>t;while(t--){fa.clear();///初始化要做好int n;cin>>n;for(int i=0;i<n;i++){cin>>xi[i]>>yi[i]>>ei[i];}///先算一遍等于号的for(int i=0;i<n;i++){int x=xi[i];int y=yi[i];if(ei[i]==1){if(fa[x]==0){fa[x]=x;///赋初值拆分进来}if(fa[y]==0){fa[y]=y;///赋初值拆分进来}//mergefa(x,y);}}///不等于的int flag=1;for(int i=0;i<n;i++){int x=xi[i];int y=yi[i];if(ei[i]==0){if(fa[x]==0){fa[x]=x;///赋初值拆分进来}if(fa[y]==0){fa[y]=y;///赋初值拆分进来}if(get(x)==get(y)){flag=0;break;}else{continue;}}}if(flag){cout<<"YES"<<endl;}else{cout<<"NO"<<endl;}}return 0;
}

在map基础上,把相等的和不等的分开存储,空间*2,时间/2,牛客能过了,acwing多过了几条数据,但还是7组

#include <iostream>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define maxn 1000005
map<int,int> fa;
int n;
int xi[maxn];
int yi[maxn];int xp[maxn];
int yp[maxn];
int get(int x)
{if(x==fa[x])///这个if应该是短路运算符///不过不加fa[x]==0||也行,已经把赋初值拆分了///map没赋过值的为0{fa[x]=x;///给没赋过值的准备的return x;}return fa[x]=get(fa[x]);
}
void mergefa(int x,int y)
{fa[get(x)]=get(y);
}
int main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int t;cin>>t;while(t--){fa.clear();///初始化要做好int n;cin>>n;int e;int bufx,bufy,bufe;int cnt1,cnt0;cnt1=cnt0=0;for(int i=0;i<n;i++){cin>>bufx>>bufy>>bufe;if(bufe==1){xi[cnt1]=bufx;yi[cnt1++]=bufy;}if(bufe==0){xp[cnt0]=bufx;yp[cnt0++]=bufy;}}for(int i=0;i<cnt1;i++){int x=xi[i];int y=yi[i];if(fa[x]==0){fa[x]=x;///赋初值拆分进来}if(fa[y]==0){fa[y]=y;///赋初值拆分进来}//mergefa(x,y);}///不等于的int flag=1;for(int i=0;i<cnt0;i++){int x=xp[i];int y=yp[i];if(fa[x]==0){fa[x]=x;///赋初值拆分进来}if(fa[y]==0){fa[y]=y;///赋初值拆分进来}if(get(x)==get(y)){flag=0;break;}else{continue;}}if(flag){cout<<"YES"<<endl;}else{cout<<"NO"<<endl;}}return 0;
}

我透了,改个unordered_map就能过,或者开O2(O2不能过)

2021.3.7复习解法(能过前九个):有个很不错的结构体写法

#include <iostream>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define maxn 1000005
int fa[maxn];
struct uneq{int a;int b;
}uneqs[maxn];
void initfa()
{for(int i=0;i<maxn;i++){fa[i]=i;}}
int getfa(int x)
{if(fa[x]==x)return fa[x];return fa[x]= getfa(fa[x]);
}
int mergefa(int a,int b)
{fa[getfa(a)]=getfa(b);
}
int main()
{int t;cin>>t;while(t--){initfa();int n;cin>>n;int cntuneq=0;int bufa,bufb,bufc;while(n--){cin>>bufa>>bufb>>bufc;if(bufc==1){mergefa(bufa,bufb);}if(bufc==0){uneqs[cntuneq++]={bufa,bufb};///新的结构体写法很有趣}}
//        for(int i=0;i<cntuneq;i++)
//        {//            cout<< uneqs[i].a<<uneqs[i].b;
//        }int flag=1;for(int i=0;i<cntuneq;i++){if(getfa(uneqs[i].a)==getfa(uneqs[i].b)){flag=0;break;}}if(flag){cout<<"YES"<<endl;}else{cout<<"NO"<<endl;}}return 0;
}

supermarket

0x17


扩展域与边带权的并查集



银河英雄传说


虽然dx的变化有一半是写在get里面的,但如果不merge,fa[x]指向的是当前根节点,根节点dx为0,dx+=d【fa【x】】不会发生改变-----------每一次merge,对每个节点只+1次,且不会影响其他同集合的节点

带图的题解

另外有的标准size是关键字,不能用,不过编译

#include <bits/stdc++.h>
using namespace std;
const int N=31000+10;
int fa[N],n,t,i,j,d[N],size[N];//size就是记录个数
int get(int x)
{if (x==fa[x])return x;int root=get(fa[x]);d[x]+=d[fa[x]];//往下推进return fa[x]=root;
}
void merge(int x,int y)
{x=get(x),y=get(y);fa[x]=y,d[x]=size[y];size[y]+=size[x];//顺带记录
}
int main()
{scanf("%d\n",&t);for(i=1;i<=30000;i++)fa[i]=i,size[i]=1;while(t--){char ch=getchar();scanf("%d %d\n",&i,&j);if (ch=='M'){merge(i,j);}else{if (get(i)==get(j))cout<<abs(d[i]-d[j])-1;elsecout<<"-1";cout<<endl;}}return 0;
}

银河英雄传说—边权集2021.3.8复习—有注释!

#include <iostream>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define maxn 100005
int fa[maxn];
int d[maxn];///记录战舰x与fa[x]之间边的权值///初值为0
int sizefa[maxn];/// 记录树的大小,初值1
void initfa()
{for(int i=0;i<maxn;i++){fa[i]=i;}}
int getfa(int x)
{if(fa[x]==x)return x;return fa[x]=getfa(fa[x]);
}
int newgetfa(int x)
{if(fa[x]==x)return x;int root=getfa(fa[x]);///先存出来,集合代表d[x]+=d[fa[x]]///树根变成了新的树根,----对边权求和///到维护前树根的距离+维护前树根到新树根的距离return fa[x]=root;}
void mergefa(int a,int b)
{fa[getfa(a)]=getfa(b);
}
void mergefa(int a,int b)///之前提到了需要+维护前树根到新树根的距离
{                           ///那么这个距离需要两个步骤d[getfa(a)]=fasize(getfa(b));///1.接到尾部,旧树根的边权d[x](到新树根距离)就是目标树的size(边数)fasize[get(fa(b))]+=fasize[getfa(b)];///2.成为新树,size变大fa[getfa(a)]=getfa(b);}
int main()
{return 0;
}

2021.4.17研究出来的模板

#include <iostream>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define maxn 1005
int fa[maxn];
int d[maxn];
void initfa()
{for(int i=1;i<=n;i++){fa[i]=i;}
}
int getfa(int x)
{if(fa[x]==x)return x;///这两行就是维护权值数组int root=fa[x];d[x]+=d[fa[x]];return fa[x]=root;
}
void mergefa(int x,int y)
{///这行是方便使用rx=getfa(x);ry=getfa(y);///这两行是维护权值数组d[rx]=d[ry]+1;//d[rx]=size(y);sizem[y]+=sizem[x];///这行是原来的fa[x]=ry;}}
int main()
{return 0;
}

奇偶游戏

边权集解法

先将正常数组改成前缀和,变成两个点的奇偶性,这样“权”就可以变成d[x](x与根之间),奇偶性的话,就用抑或来计算,如果已经有了,那么通过dx来计算x与y之间奇偶性,如果没有联通,那么要通过已知x与y之间奇偶性,倒推两个根节点之间的奇偶性,合并,另外数很稀疏,考虑离散化


acwing秦淮河大佬的复现书上代码,思路很棒

#include<bits/stdc++.h>
using namespace std;
const int N=10010<<1;
struct node
{int l,r,ans;
} q[N];
int a[N],fa[N],d[N],n,m,t_n;
int get(int x)
{if (x==fa[x])return x;int root=get(fa[x]);d[x]^=d[fa[x]];//异或return fa[x]=root;
}
inline int read_init()//离散化
{cin>>n>>m;for(int i=1;i<=m;i++){char str[5];scanf("%d%d%s",&q[i].l,&q[i].r,str);q[i].ans=(str[0]=='e'?0:1);a[++t_n]=q[i].l-1;a[++t_n]=q[i].r;}sort(a+1,a+1+t_n);n=unique(a+1,a+1+t_n)-a-1;//去重
}
inline int work()
{read_init();for(int i=1;i<=n;i++)fa[i]=i;for(int i=1;i<=m;i++){int x=lower_bound(a+1,a+1+n,q[i].l-1)-a;//离散化后要找数int y=lower_bound(a+1,a+1+n,q[i].r)-a;int p=get(x),q2=get(y);if (p==q2){if ((d[x]^d[y])!=q[i].ans)//变量要相等,但是却不相等了.{cout<<i-1<<endl;return 0;}}else{fa[p]=q2;//合并merge.两方代码就懒得写函数了,见谅d[p]^=d[x]^d[y]^q[i].ans;//统统异或}}cout<<m;//数据过于优秀,一个问题都没有
}
int main()
{work();return 0;
}

扩展域解法(这个很简单,维护两个域,互相也是联通的,不用算权值了)


//Wan Hong 3.0
//notebook
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>typedef long long ll;
typedef std::pair<ll,ll> pll;
ll read()
{ll x=0,f=1;char c=getchar();while(c<'0'||c>'9'){if(c=='-')f=-1;else c=getchar();}while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();return f*x;
}
ll min(ll a,ll b)
{return a<b?a:b;
}
ll max(ll a,ll b)
{return a>b?a:b;
}
bool umin(ll &a,ll b)
{if(b<a)return a=b,1;return 0;
}
bool umax(ll &a,ll b)
{if(b>a)return a=b,1;return 0;
}
ll abs(ll x)
{return x>0?x:-x;
}
/**********/
#define MAXN 100011
struct ufs
{ll fa[MAXN];void build(ll n){for(ll i=0;i<=n;++i)fa[i]=i;}ll find(ll x){if(fa[x]==x)return x;return fa[x]=find(fa[x]);}void uni(ll u,ll v){u=find(u),v=find(v);fa[u]=v;}bool same(ll u,ll v){return find(u)==find(v);}
}s;
struct query
{ll l,r,k;query(){}query(ll _l,ll _r,ll _k){l=_l,r=_r,k=_k;}
}q[MAXN];
ll a[MAXN];
ll cnt=0;
void disc()
{std::sort(a+1,a+cnt+1);cnt=std::unique(a+1,a+cnt+1)-(a+1);
}
ll place(ll x)
{return std::lower_bound(a+1,a+cnt+1,x)-a;
}
int main()
{ll n=read(),m=read();for(ll i=1;i<=m;++i){ll l=read()-1,r=read();char c=getchar();while(c!='e'&&c!='o')c=getchar();q[i]=query(l,r,c=='o');a[++cnt]=l,a[++cnt]=r;}disc();s.build(cnt<<1);//[1,cnt]:x_even;[cnt+1,2cnt]:x_oddfor(ll i=1;i<=m;++i){ll l=place(q[i].l),r=place(q[i].r),k=q[i].k;ll l_even=l,l_odd=l+cnt,r_even=r,r_odd=r+cnt;if(!k){if(s.same(l_odd,r_even)||s.same(l_even,r_odd)){printf("%lld\n",i-1);return 0;}else s.uni(l_odd,r_odd),s.uni(l_even,r_even);}else{if(s.same(l_even,r_even)||s.same(l_odd,r_odd)){printf("%lld\n",i-1);return 0;}else s.uni(l_even,r_odd),s.uni(l_odd,r_even);}}printf("%lld",m);return 0;
}作者:whsstory
链接:https://www.acwing.com/solution/content/4338/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

扩展域解法1.不要忘了初始化2.不要忘了-1 3.扩展域一定要放一个数组里 ------------2021.3.8复习

#include <iostream>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define maxn 100005
int fa[maxn];///扩展域应该放在同一个数组里使用,x,x+n,x+n+n,x+n+n+n,......这样才能测试是否联通
int d[maxn];
int sizefa[maxn];
void initfa()
{for(int i=0;i<maxn;i++){fa[i]=i;}}
int getfa(int x)
{if(fa[x]==x)return x;return fa[x]=getfa(fa[x]);
}
void mergefa(int a,int b)
{fa[getfa(a)]=getfa(b);
}
int main()
{initfa();int n;cin>>n;int t;cin>>t;int t2=t;int a,b,op;while(t--){cin>>a>>b>>op;if(op==0)///even{if(getfa(a-1)==getfa(b+n))///is odd--矛盾{cout<<t2-t<<'*';return 0;}mergefa(a-1,b);mergefa(a-1+n,b+n);}else{if(getfa(a-1)==getfa(b)){cout<<t2-t<<"#";return 0;}mergefa(a-1,b+n);mergefa(a-1+n,b);}}return 0;
}

食物链

拓展域

三个域

//这里我们将三个域,分别转化为了n,n+n,n+n+n.因为读入方面特别烦.
#include <bits/stdc++.h>
using namespace std;
int fa[200000];
int n,m,k,x,y,ans;
int get(int x)
{if(x==fa[x])return x;return fa[x]=get(fa[x]);
}
void merge(int x,int y)
{fa[get(x)]=get(y);
}
int main()
{cin>>n>>m;for(int i=1;i<=3*n;i++)fa[i]=i;for(int i=1;i<=m;i++){scanf("%d%d%d",&k,&x,&y);if(x>n || y>n)ans++;///假话总数+1else if(k==1)///同类{if(get(x)==get(y+n) || get(x)==get(y+n+n))//如果x,y是同类,但是x是y的捕食中的动物,或者x是y天敌中的动物,那么错误.ans++;///假话总数+1else{merge(x,y);merge(x+n,y+n);merge(x+n+n,y+n+n);}}else///X捕食Y{if(x==y || get(x)==get(y) || get(x)==get(y+n))//x就是y,或者他们是同类,再或者是y的同类中有xans++;//都是假话else{merge(x,y+n+n);//y的天敌域加入xmerge(x+n,y);//x的捕食域加入ymerge(x+n+n,y+n);//x的天敌域是y的捕食域.}}}cout<<ans<<endl;
}
//x是同类域.
//x+n是捕食域
//x+n+n是天敌域

2021.3.8复习:这里的捕食域,同类域,天敌域,通过三个域表达出了方向关系(X被Y捕食,Y是X的天敌):通过X的Xself 与 Y的 Yeat 联通

边带权

把吃,被吃,同类设为 1,2,0,每次维护就好

#include<bits/stdc++.h>
using namespace std;
const int maxn = 5e4 + 233;
int fa[maxn], d[maxn];
int ff(int x)
{if(fa[x] == x) return x;int r = ff(fa[x]);d[x] += d[fa[x]];return fa[x] = r;
}
int main()
{int n,k; cin >> n >> k;for(int i = 0; i <= n; i++) fa[i] = i;int ans = 0;for(int i = 1; i <= k; i++){int t, a, b;scanf("%d%d%d", &t, &a, &b);if(a > n || b > n) {ans ++; continue;}else if(t == 2 && a == b) {ans++; continue;}else{int rel;if(t == 2) rel = 1;else rel = 0;int x = ff(a), y = ff(b);if(x == y) {if((((d[a] - d[b]) % 3) + 3) % 3 != rel)ans++;}else{fa[x] = y;d[x] = d[b] - (d[a] - rel);}}}cout<< ans;
}作者:这个显卡不太冷
链接:https://www.acwing.com/solution/content/1357/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

蓝桥备赛第四周 同余+并查集相关推荐

  1. 【蓝桥备赛冲刺】2022年第十三届省赛模拟题题解C/C++

    食用该篇博客前须知: (0)第一次写博客,如有地方处理不好请见谅,后续会不断提高自己的写博客能力. (1)在头文件处偷了懒,使用的都是万能头文件.(最好还是自己要记住常用头文件 (2)使用的是C++, ...

  2. 问题 1433: [蓝桥杯][历届试题]危险系数(并查集and暴力)

    问题 1433: [蓝桥杯][历届试题]危险系数 时间限制: 1Sec 内存限制: 128MB 提交: 123 解决: 39 题目描述 问题描述 抗日战争时期,冀中平原的地道战曾发挥重要作用. 地道的 ...

  3. 蓝桥备赛第一周2021.1.11 递归 枚举 位运算

    文章目录 递归实现指数型枚举 递归指数型枚举 方法1:肯定是2^n行,所以直接就是上一个动态m从0到n加一堆空行 方法2:以最新的值为n为结束,遇到为0的不输出,用完要恢复为0 递归实现排列型枚举 非 ...

  4. 蓝桥备赛第三周 倍增+贪心+素数+约数

    文章目录 0X06倍增 天才ACM(有空再做) 0X07贪心 防晒 将乳液按SPF从大到小,牛按minSPF从大到小排序 牛客有个题解都从小到大也过了 原理 畜栏预定 ~~按结束时间从小到大排~~ 按 ...

  5. 蓝桥备赛第二周 前缀和

    文章目录 前缀和与差分数组 [HNOI2003]激光炸弹 前缀和解法(他又不变,,,前缀和就能搞定吧?) 这种地方出现的错误(部分数据过不去)可能是少个等于之类的边界问题 2021-3-10复习,这里 ...

  6. 【蓝桥备赛】七星填空

    题目 如下图所示.在七角星的 14 个节点上填入 1 ~ 14的数字,不重复,不遗漏. 要求每条直线上的四个数字之和必须相等. 图片描述 图中已经给出了 3 个数字. 请计算其它位置要填充的数字,答案 ...

  7. 计蒜客蓝桥杯模拟赛5 引爆炸弹【并查集】

    在一个 n×m 的方格地图上,某些方格上放置着炸弹.手动引爆一个炸弹以后,炸弹会把炸弹所在的行和列上的所有炸弹引爆,被引爆的炸弹又能引爆其他炸弹,这样连锁下去. 现在为了引爆地图上的所有炸弹,需要手动 ...

  8. 2017乌鲁木齐区域赛I(带权并查集)

    #include<bits/stdc++.h> using namespace std; int f[200010];//代表元 long long rl[200010];//记rl[i] ...

  9. 中石油训练赛 - 奎奎画画(思维+并查集+离线处理)

    题目描述 "为你写诗,为你静止,为你做不可能的事",爱情是一种怪事,它让奎奎开始学习画画.奎奎认为一张画的艺术价值等于画上的白色联通块个数(当一个格子和它上下左右四个方向上的某个相 ...

最新文章

  1. jdbc插入数据_JMeter数据库测试计划
  2. [C][变量作用域]语句块
  3. 使用C#和Excel进行报表开发(四)-复制单元格 【转】
  4. Mobius函数计算 定义+代码模板
  5. MongoDB 安装与基本命令
  6. Kaggle新赛 | 医学影像插管分类,总奖池 5 万美金
  7. 扩展JavaScript原生方法
  8. 使用Mathcad解受迫振动微分方程并画图
  9. 【如何注销CSDN账号】说容易也容易,说难也难
  10. 关于sublime出现PyV8binary错误
  11. 查找、下载芯片手册推荐网址
  12. 服务器raid发生故障如何恢复数据?- raid5磁盘阵列数据恢复方法
  13. 树莓派+PHP+Mairadb数据库读取DHT11
  14. [转载]受 Windows XP SP2 影响的软件列表
  15. 面向对象的6大原则与3大特性
  16. Java实现Redis的列表(List)命令
  17. 如何提高项目估算精准度?关键看5大影响因子
  18. 【工作】论文格式详细要求
  19. 趣店新项目万里目,百亿补贴计划,能烧出一个未来吗
  20. excel中用正则匹配_Excel利用正则表达式匹配和替换内容

热门文章

  1. HDU 3308 线段树求区间最长连续上升子序列长度
  2. Pwn_9 作业讲解
  3. jquery 判断手势滑动方向(上下左右)
  4. 树莓派2+无线网卡=钓鱼热点
  5. 如何让在JAVA中定义常量池
  6. cocos2d-x中集成protoc-gen-lua
  7. HDU 4282 A very hard mathematic problem 二分题目
  8. 有关WriteableBitmap和BitmapImage之间的相互转换
  9. 得到按钮所在DIV的ID
  10. 斗鱼mac html5,New API · Issue #28 · spacemeowx2/DouyuHTML5Player · GitHub