AtCoder Regular Contest 111

0.A - Simple Math 2

\( 让我非常自闭的一道题,当时题还读反了,要求输出\lfloor \frac{10^N}{M} \rfloor\%M\\ 1<=N<=10^{18}\\ 1<=M<=10^4\\ 已知\lfloor \frac{\lfloor \frac{A}{B} \rfloor }{C} \rfloor = \lfloor \frac{A}{B*C} \rfloor 同理应该有\lceil \frac{\lceil \frac{A}{B} \rceil }{C} \rceil = \lceil \frac{A}{B*C} \rceil\\ A\%B=A- \lfloor \frac{A}{B} \rfloor*B \\ 记Ans=\lfloor \frac{10^N}{M} \rfloor - \lfloor \frac{10^N}{M*M} \rfloor *M\\ Q=\lfloor \frac{10^N}{M} \rfloor , Q^\prime=\lfloor \frac{10^N}{M*M} \rfloor 由下取整得\\ 10^N = Q * M + R \\ Q = \frac {10^N - R}{M} \\ 10^N = Q^\prime * M^2 + R^\prime\\ Q^\prime = \frac {10^N - R^\prime}{M^2} 所以有:\\ A = Q - Q^\prime * M\\ A = \frac{(10^N - R) - (10^N - R^\prime) }{M} =\frac{R^\prime-R}{M}\\ =\frac {(10^N\%M^2 - 10^N\%M)}{M} 总结就是%和下取整符号想办法化简掉就ok了 套个快速幂和龟速乘的板子就行了\\ \)
\( 两行的python3标答离谱\\ \lfloor \frac{10^N - kM^2}{M} \rfloor \equiv \lfloor \frac{10^N}{M} - kM \rfloor \equiv \lfloor \frac{10^N}{M} \rfloor - kM \equiv \lfloor \frac{10^N}{M} \rfloor \pmod M (k \in \mathbb{Z}) \)

n, m = map(int, input().split())
print(pow(10, n, m * m) // m % m)
#include<iostream>
#include<algorithm>
using namespace std;

/*
ans= (10^N%(M^2)-10^N%M )/M
*/
typedef long long ll;
ll qmd(ll a,ll b,ll c);
ll qmi(ll a,ll b,ll c)
{
    ll ans=1;
    while(b)
    {
        if(b&1)
            ans=qmd(ans,a,c)%c;
        b>>=1;
        a=qmd(a,a,c)%c;
    }
    return ans;
}

ll qmd(ll a,ll b,ll c)
{
    //快速乘
    ll ans=0;
    while(b)
    {
        if(b&1)
            ans=(ans+a)%c;
        a=(a+a)%c;
        b>>=1;
    }
    return ans;
}
int main()
{
    ll n,m;cin>>n>>m;
    cout<<(qmi(10,n,m*m)-qmi(10,n,m))/m;
    return 0;
}

1.小希的迷宫

\( 无向图判断是不是一棵树,坑点空图也是yes,自环是yes\\ 只要判断这个无向图不存在一个节点有多个父亲,并且只\\ 有唯一一个根(保证是连通图)即可 \)

#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
/*
并查集判有无环 
*/
const int N=2e5+10;
bool flag=true;
int fa[N];
bool vis[N];
int find(int x)
{
	if(x!=fa[x])
		fa[x]=find(fa[x]);
	return fa[x];
}

void merge(int x,int y)
{
	vis[x]=vis[y]=1;
	if(find(x)!=find(y))
		fa[find(x)]=find(y);
	else if(x!=y)//排除自环,有点坑 
		flag=false;
}

void init()
{
	for(int i=1;i<=N;i++)
		fa[i]=i;
	for(int i=1;i<=N;i++)
		vis[i]=0;
}
int main()
{
	int n,m;
	init();
	while(cin>>n>>m,n!=-1&&m!=-1)
	{
		if(n==0&&m==0)//输入结束判断 
		{
			bool nul=1;
			for(int i=1;i<=N;i++)
				if(vis[i])
					nul=0;
			if(nul)
				{cout<<"Yes"<<endl;continue;}
			if(!flag)
				cout<<"No"<<endl;
			else
			{
				int cnt=0;
//				cout<<" "<<cnt<<endl;
				for(int i=1;i<=N;i++)
					if(vis[i]&&i==fa[i])
						cnt++;
				if(cnt==1)
					cout<<"Yes"<<endl;
				else
					cout<<"No"<<endl;	
			}
			init();
			flag=true; 
		}
		else
			merge(n,m);
	}
	return 0;
}

2.Is It A Tree?

\( 从无向图变成了有向图,1\;2\;3\;2\;0\;0 是no,因为细节wa了很久,血炸 \)

#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
/*
并查集判有无环 
*/
const int N=2e5+10;
bool flag=true;
int fa[N];
bool vis[N];
int find(int x)
{
	if(x!=fa[x])
		fa[x]=find(fa[x]);
	return fa[x];
}

void merge(int x,int y)
{
	vis[x]=vis[y]=1;
	if(find(x)!=find(y))
		fa[find(x)]=find(y);
	else if(x!=y)//排除自环,有点坑 
		flag=false;
}

void init()
{
	for(int i=1;i<=N;i++)
		fa[i]=i;
	for(int i=1;i<=N;i++)
		vis[i]=0;
}
int main()
{
	int n,m;
	init();
	while(cin>>n>>m,n!=-1&&m!=-1)
	{
		if(n==0&&m==0)//输入结束判断 
		{
			bool nul=1;
			for(int i=1;i<=N;i++)
				if(vis[i])
					nul=0;
			if(nul)
				{cout<<"Yes"<<endl;continue;}
			if(!flag)
				cout<<"No"<<endl;
			else
			{
				int cnt=0;
//				cout<<" "<<cnt<<endl;
				for(int i=1;i<=N;i++)
					if(vis[i]&&i==fa[i])
						cnt++;
				if(cnt==1)
					cout<<"Yes"<<endl;
				else
					cout<<"No"<<endl;	
			}
			init();
			flag=true; 
		}
		else
			merge(n,m);
	}
	return 0;
}

3.B - Reversible Cards

思路A:
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
/*
判断这个无向图的每个连通块是否是树 
*/
using namespace std;
 
/*
创建一个颜色图,并不断删除度为1的顶点。最终的答案是删除顶点的数目加上次数大于1的余数。



任何度等于1的顶点,只有一次被选择的机会。在对这些顶点进行重定时的过程结束时,度数大于1的顶点可以放入一个循环中,使它们被选中。
*/
#define INF 1000000000
#define MAXN 200010
#define MAXTAM 400010
 
int n;
int a[MAXN], b[MAXN];
 
vector<int> g[MAXTAM];
int deg[MAXTAM];
 
int main() {
    scanf("%d", &n);
    int i;
    for (i=1; i<=n; i++) {
        scanf("%d %d", &a[i], &b[i]);
        g[a[i]].push_back(b[i]);
        g[b[i]].push_back(a[i]);
        deg[a[i]]++;
        deg[b[i]]++;
    }
 
 
    queue<int> que;
    for (i=0; i<MAXTAM; i++) {
        if (deg[i]==1) {
            que.push(i);
        }
    }
 
    int ans = 0;
    while (!que.empty()) {
        int u = que.front();
        que.pop();
        if (deg[u]==1) {
           // printf("**** %d\n", u);
            deg[u]--;
 
            ans++;
            for (i=0; i<g[u].size(); i++) {
                int v = g[u][i];
                deg[v]--;
                if (deg[v]==1) {
                    que.pu	sh(v);
                }
            }
        }
    }
    for (i=0; i<MAXTAM; i++) {
        if (deg[i]>=2) {
            ans++;
        }
    }
    printf("%d\n", ans);
    return 0;
}


思路B:
#include <bits/stdc++.h>
using namespace std;
int n,ans,a,b,fa[400050],t[400050];
 
int Fa(int x) {
	if (fa[x]==x) return x;
	return fa[x]=Fa(fa[x]);
}
 
int main() {
	for (int i=1; i<=400000; ++i) fa[i]=i;
	cin>>n;
	while (n--) {
		scanf("%d%d",&a,&b);
		if (Fa(a)!=Fa(b)) {
			if (t[Fa(a)]&&t[Fa(b)]) t[Fa(b)]=1;
			else t[Fa(b)]+=t[Fa(a)],++ans;
			fa[Fa(a)]=Fa(b);
		} else if (!t[Fa(a)])
			t[Fa(a)]=1,++ans;
	}
	cout<<ans;
}
posted @ 2021-01-10 10:39  30天CF上蓝!!!  阅读(139)  评论(0编辑  收藏  举报