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;
}