AtCoder Regular Contest 111

由于不想被退学忙于学习,好久不打了……

A

感觉不是那么签到……问题可以转化为10^n=am^2+bm+c,求b,然后就转化为普通的快速幂即可

#include<bits/stdc++.h>
using namespace std;
long long n;
int m,a=10,ret=1;
int main()
{
    cin>>n>>m;
    while(n)
    {
        if(n%2)ret=1ll*ret*a%(m*m);
        a=1ll*a*a%(m*m),n>>=1;
    }
    printf("%d\n",ret/m);
}
View Code

B

发现如果把每一张卡片视为一条无向边(ai,bi),答案就是每个连通块中点数和边数的最小值,证明可以任取连通块中的一棵生成树,尝试加边即可证明。

#include<bits/stdc++.h>
using namespace std;
const int N=4e5+7;
int n,ans,f[N],sz[N],e[N];
int find(int x){return x==f[x]?x:f[x]=find(f[x]);}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=4e5;i++)sz[i]=1,f[i]=i;
    for(int i=1,x,y;i<=n;i++)
    {
        scanf("%d%d",&x,&y);
        x=find(x),y=find(y);
        if(x!=y)f[x]=y,sz[y]+=sz[x],e[y]+=e[x]+1;
        else e[x]++;
    }
    for(int i=1;i<=4e5;i++)ans+=min(e[find(i)],sz[find(i)]),e[find(i)]=sz[find(i)]=0;
    printf("%d\n",ans);
}
View Code

C

容易发现对每一个目标箱子不在自己手上的人,体重重于目标箱子即可,然后从体重轻的开始交换就行了,但是由于细节WA了一发导致本身不高的名次更加难堪

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+7;
struct node{int x,id;}a[N];
int n,m,b[N],p[N],pid[N],aa[N],ab[N],pos[N];
bool cmp(node a,node b){return a.x<b.x;}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i].x),a[i].id=i;
    for(int i=1;i<=n;i++)scanf("%d",&b[i]);
    for(int i=1;i<=n;i++)scanf("%d",&p[i]),pid[p[i]]=i;
    for(int i=1;i<=n;i++)if(i!=p[i]&&a[i].x<=b[p[i]]){puts("-1");return 0;}
    sort(a+1,a+n+1,cmp);
    for(int i=1;i<=n;i++)
    if(p[a[i].id]!=a[i].id)
    {
        int now=a[i].id;
        aa[++m]=now,ab[m]=pid[now];
        p[pid[now]]=p[now],pid[p[now]]=pid[now];
    }
    printf("%d\n",m);
    for(int i=1;i<=m;i++)printf("%d %d\n",aa[i],ab[i]);
}
View Code

D

石乐志没想出这题……

就是c相同时随便连一连,不同时从大的连到小的就行了

#include <bits/stdc++.h>
using namespace std;
const int N=1e4+7;
int n,m,a[N],b[N],c[N];
bool e[N][N],vis[N];
vector<int>G[N];
void dfs(int u)
{
    vis[u]=1;
    for(int v:G[u]) 
    if(c[u]>c[v]||c[u]==c[v]&&!e[u][v]&&!e[v][u])
    {
        e[u][v]=1;
        if(!vis[v])dfs(v);
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    scanf("%d%d",&a[i],&b[i]),G[a[i]].push_back(b[i]),G[b[i]].push_back(a[i]);
    for(int i=1;i<=n;i++)scanf("%d",&c[i]);
    for(int i=1;i<=n;i++)if(!vis[i])dfs(i);
    for(int i=1;i<=m;i++)if(e[a[i]][b[i]])puts("->");else puts("<-");
}
View Code

E

数学退化了

记l=A+Bi,r=A+Ci,原题可转化成求使得[(l-1)/D]==[r/D]的i的个数,易得i<=(D-2)/(C-B),令k=(D-2)/(C-B),正难则反,可以求不等于的个数,也就是Σ([(A+Ci)/D]-[(A+Bi-1)/D]),然后要求用O(log(D))的时间求形如Σ[(a+bi)/c]的值,这个可以用类欧几里得去做,可惜我都忘了QAQ

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll f(ll a,ll b,ll c,ll n)
{
    if(!a)return(n+1)*(b/c);
    if(a>=c||b>=c)return(f(a%c,b%c,c,n)+(a/c)*n*(n+1)/2+b/c*(n+1));
    ll m=(a*n+b)/c;
    return n*m-f(c,c-b-1,a,m-1);
}
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        ll a,b,c,d,k;scanf("%lld%lld%lld%lld",&a,&b,&c,&d);
        k=(d-2)/(c-b);
        printf("%lld\n",k-f(c,a,d,k)+a/d+f(b,a-1,d,k)-(a-1)/d);
    }
}
View Code

新号打的

rank371 performance=1978 rating=778

posted @ 2021-01-13 15:08  hfctf0210  阅读(169)  评论(0编辑  收藏  举报