AtCoder Regular Contest 111

0.A - Simple Math 2

( 让我非常自闭的一道题,当时题还读反了,要求输出lfloor frac{10^N}{M} floor\%M\ 1<=N<=10^{18}\ 1<=M<=10^4\ 已知lfloor frac{lfloor frac{A}{B} floor }{C} floor = lfloor frac{A}{B*C} floor 同理应该有lceil frac{lceil frac{A}{B} ceil }{C} ceil = lceil frac{A}{B*C} ceil\ A\%B=A- lfloor frac{A}{B} floor*B \ 记Ans=lfloor frac{10^N}{M} floor - lfloor frac{10^N}{M*M} floor *M\ Q=lfloor frac{10^N}{M} floor , Q^prime=lfloor frac{10^N}{M*M} floor 由下取整得\ 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} floor equiv lfloor frac{10^N}{M} - kM floor equiv lfloor frac{10^N}{M} floor - kM equiv lfloor frac{10^N}{M} floor 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
", 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
", 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;
}
原文地址:https://www.cnblogs.com/forward-985/p/14257536.html