• EOJ Monthly 2017.12


    A

    签到


    B. 在哈尔滨的寒风中

    题意

    给一个n×m的棋盘,问有多少对点可以互相到达(可以经过若干步)(n,m<=1e9)

    分析

    很显然,当棋盘很大时,所有点对都可以互相到达(比如:象棋棋盘),模拟可得:这个边界为3*4(大于等于3*4所有点都可到达),其他情况手动暴力模拟即可

    还有另一种思路:找不到边界是我们可以假设边界为100*100(因为数据很大,不能直接暴力dfs),剩下暴力dfs找属于同一联通块的即可

    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    
    const int maxn = 1e5+5 ;
    const int maxm = 1e5 + 3;
    const ll mod = 1e9+7;
    
    ll n,m;
    
    int main()
    {
        scanf("%lld%lld", &n ,&m);
        if(n>m)
            swap(n,m);
        if(n>=3&&m>=4)
        {
            ll ans=n*m;
            printf("%lld
    ", (ans*(ans-1))/2);
        }
        else if(n==3&&m==3)
            printf("28
    ");
        else if(n==2)
        {
            ll ans1=((m+1)/2);
            ll ans2= (m-(m+1)/2);
            cout<<(ans1*(ans1-1))+(ans2*(ans2-1))<<endl;
        }
        else
            cout<<0<<endl;
        return 0;
    }
    View Code

     *C. 易位构词

    题意

    给一个单词s (1|s|105),问你是否存在一种改变字符的顺序使得每个字符都不在原来的位置上,存在输出单词,否则输出"impossible"

    分析

    直接将单词排序,循环向右移动最大连续相同的字符个数即可(具体实现还是有点困难的,学习!!!

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e5+5;
    const int maxm=1e5+5;
    
    int cnt[maxn];
    char str[maxn];
    char ans[maxn];
    
    struct node
    {
        char s;int id;
        friend bool operator < (node x, node y)
        {
            if(cnt[x.s]!=cnt[y.s])
            return cnt[x.s]>cnt[y.s] ;
            return x.s<y.s;
        }
    }a[maxn];
    
    int main()
    {
        scanf("%s", str);
        int n=strlen(str);
        for(int i=0;i<n;i++) a[i]={str[i],i}, cnt[str[i]]++;
        sort(a,a+n);
        int mx=0;
        char ss=a[0].s;
        int i;
        for(i=0;i<n;i++) if(a[i].s!=ss) break;
        mx=i;
        if((mx<<1)>n) printf("impossible
    ");
        else
        {
            for(int i=0;i<n;i++)  str[(i+mx)%n]=a[i].s;
            for(int i=0;i<n;i++)  ans[a[i].id]=str[i];
            ans[n]='';
            printf("%s", ans);
        }
        return 0;
    }
    View Code

    D. 唐纳德和他的数学老师
    题意
    简单二分图题
    分析
    直接建边,跑匈牙利算法,找不到就跳出即可,用到欧拉函数,注意分解不了时,要考虑进去
     
    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    
    const int maxn = 3000+10;
    const int N = 1e6+5;
    
    int prime[N], a[maxn];
    bool ok[N],used[N];
    int boy[N];
    int head[N];
    int num;
    int cnt;
    
    struct node
    {
        int nex, to;
    }edge[N];
    
    void addedge(int u,int v)
    {
        ++num;
        edge[num].to=v;
        edge[num].nex=head[u];
        head[u]=num;
    }
    
    void init()
    {
        cnt=num=0;
        memset(ok,0, sizeof(ok));
        memset(head,0,sizeof(head));
        memset(boy, 0, sizeof(boy));
    }
    
    void ol()
    {
        ok[1]=1;
        for(int i=2;i<1005;i++)
        {
            if(!ok[i])
            {
                prime[cnt++]=i;
                for(int j=i;j<1005;j+=i)
                {
                    ok[j]=1;
                }
            }
        }
    }
    
    bool found(int x)
    {
        for(int i=head[x]; i!=0; i=edge[i].nex)
        {
            int u=edge[i].to;
            if(!used[u])
            {
                used[u]=1;
                if(boy[u]==0 || found(boy[u]))
                {
                    boy[u]=x;
                    return 1;
                }
            }
        }
        return 0;
    }
    
    int main()
    {
        int n;
        ol();
        scanf("%d", &n);
        for(int i=1;i<= n;i++)
        {
            scanf("%d", &a[i]);
            int ans=a[i];
            for(int j=0;j<cnt;j++)
            {
                if(prime[j]>ans)
                    break;
                if(ans%prime[j]==0)
                    addedge(i,j+1);
                while(ans&&ans%prime[j]==0)
                    ans/=prime[j];
            }
            if(ans!=1)
                addedge(i,ans);
        }
        int sum=0;
        for(int i=1;i<=n;i++)
        {
            memset(used,0,sizeof(used));
            if(found(i)) sum++;
            else   break;
        }
        printf("%d
    ", sum);
        return 0;
    }
    View Code
     

     

    要么优秀要么生锈
  • 相关阅读:
    C#使用GZipStream压缩与解压字符串
    C# 参考之方法参数关键字:params、ref及out
    C#中cookie讲解
    WPF中窗口控件的跨线程调用
    vs2010 快捷键大全
    Python线程池
    Python 爬虫修正
    Python 爬虫插件
    Python发现爬虫插件有BUG。
    Python 存在BUG的线程池
  • 原文地址:https://www.cnblogs.com/Superwalker/p/8006991.html
Copyright © 2020-2023  润新知