zoukankan      html  css  js  c++  java
  • 2016年中国大学生程序设计竞赛(合肥)-重现赛

    A.传递

    赛后AC数最多的2016合肥题。赛时没看到是竞赛图,以为是o(n^3)果断放弃

    后面才看到。。。一开始想到用补图的2个方向去补原图再判圈,光荣TLE--边数也太多了吧!

    后用其他人的判传递法才成功控制时间AC

    感觉如果非要判圈,有些数据可以卡dfs

    判传递也太简单了。。。从一个点开始覆盖点,如果有2边链且不被传递,到那边的点,会发现还没覆盖,标上2,退出走人

    #include <bits/stdc++.h>
    
    using namespace std;
    typedef double db;
    typedef long long ll;
    typedef unsigned int uint;
    typedef unsigned long long ull;
    const db eps=1e-6;
    #define lson l, m, rt << 1
    #define rson m + 1, r, rt << 1 | 1
    #define CLR(a, b) memset(a, b, sizeof(a))
    
    const int N=5000,M=7000000;//2500*2,2500*2499/2*2
    int head[N],cnt,n;
    int to[M],nxt[M];
    char vis[N];
    
    void addedge(int u,int v)
    {
        to[cnt]=v;nxt[cnt]=head[u];head[u]=cnt++;
    }
    int que[N];
    bool bfs(int u)
    {
        memset(vis,0,sizeof(vis));
        int tal=0,hed=0;
        que[tal++]=u;
        while(tal!=hed)
        {
            int u=que[hed++];
            for(int i=head[u];i!=-1;i=nxt[i])
            {
                int v=to[i];
                if(vis[v])continue;
                vis[v]=vis[u]+1;que[tal++]=v;
                if(vis[v]>=2)return true;
            }
        }
        return false;
    }
    bool Bfs(int s)
    {
        for(int i=0;i<n+n;i++)
        {
            if(bfs(i))return true;
        }
        return false;
    }
    char str[N];
    int main()
    {
        int t,i,j,m,p;
        scanf("%d",&t);
        for(int h=0;h<t;h++)
        {
            scanf("%d",&n);getchar();
            memset(head,-1,sizeof(head));cnt=0;
            for(i=0;i<n;i++)
            {
                gets(str);
                for(j=0;j<n;j++)
                {
                    if(str[j]=='P')addedge(i,j);
                    else if(str[j]=='Q')addedge(n+i,n+j);
                }
            }
            if(Bfs(0))
            {
                puts("N");
            }
            else
            {
                puts("T");
            }
        }
        return 0;
    }
    View Code

    C.朋友

    模拟此套题时以为离根隔偶数条边的边要算sg值,反之不要

    结果这个思路是错的。。。还以为此题有多大的复杂度呢

    再做就知道了,不管根结点与1边隔了多少0边,只要中间隔了0边,要动这条1边,要做偶数次才能消除此链上的所有1边

    所以加边只是往边的两侧反转标记,标记是奇数说明操作奇数次,G赢;否则就是偶数次,B赢

    单纯的找规律题

    #include <bits/stdc++.h>
    
    using namespace std;
    typedef double db;
    typedef long long ll;
    typedef unsigned int uint;
    typedef unsigned long long ull;
    const db eps=1e-6;
    const int M=100010;
    #define lson l, m, rt << 1
    #define rson m + 1, r, rt << 1 | 1
    #define CLR(a, b) memset(a, b, sizeof(a))
    
    const int N=40010;
    set<int> s[N];
    char fag[N];
    int main()
    {
        int t,i,j,n,m,p;
        scanf("%d",&t);
        for(int h=0;h<t;h++)
        {
            memset(fag,0,sizeof(fag));
            scanf("%d%d",&n,&m);
            for(i=0;i<n;i++)s[i].clear();
            for(i=0;i<n-1;i++)
            {
                int u,v,fl;
                scanf("%d%d%d",&u,&v,&fl);u--,v--;
                if(fl==1)fag[v]^=1,fag[u]^=1,s[u].insert(v),s[v].insert(u);
            }
            for(i=0;i<m;i++)
            {
                int op,x,y,z;
                scanf("%d",&op);
                if(op==0)
                {
                    scanf("%d",&x);x--;
                    if(fag[x]==1)puts("Girls win!");
                    else puts("Boys win!");
                }
                else
                {
                    scanf("%d%d%d",&x,&y,&z);x--,y--;
                    set<int>::iterator sit1=s[x].find(y);
                    set<int>::iterator sit2=s[y].find(x);
                    if(sit1!=s[x].end() && z==0)
                    {
                        s[x].erase(sit1);s[y].erase(sit2);
                        fag[x]^=1,fag[y]^=1;
                    }
                    if(sit1==s[x].end() && z==1)
                    {
                        s[x].insert(y);s[y].insert(x);
                        fag[x]^=1,fag[y]^=1;
                    }
                }
            }
        }
        return 0;
    }
    View Code

    D.平行四边形

    (本渣不会用几何画板,用的画图请见谅)下见解析几何部分:

    顺带吐槽一句:你们转发x姐的题解不知道自己算吗

    E.扫雷

    表示还是太简单了。。转移状态什么的就搞定了

    可以用上1行有多少个雷来转移系数

    //看看会不会爆int!数组会不会少了一维!
    //取物问题一定要小心先手胜利的条件
    #include <bits/stdc++.h>
    using namespace std;
    #pragma comment(linker,"/STACK:102400000,102400000")
    #define LL long long
    #define ALL(a) a.begin(), a.end()
    #define pb push_back
    #define mk make_pair
    #define fi first
    #define se second
    #define haha printf("haha
    ")
    const int maxn = 1e4 + 5;
    const LL mod = 100000007;
    LL dp[maxn];
    char ch[maxn];
    int a[maxn];
    int n;
    int p[3] = {1, 2, 1};
    
    LL solve(){
        LL ans = 0;
        for (int i = 0; i <= 2 && i <= a[1]; i++){
            if (a[1] - i > 2) continue;
            dp[1] = a[1] - i;
            for (int j = 2; j <= n; j++){
                dp[j] = a[j - 1] - dp[j - 1] - dp[j - 2];
            }
            if (dp[n] + dp[n - 1] != a[n]) continue;
            LL res = 1;
            for (int j = 1; j <= n; j++){
                res = res * p[dp[j]];
                if (res > mod) res %= mod;
            }
            ans = (ans + res) % mod;
        }
        return ans;
    }
    
    int main(){
        int t; cin >> t;
        while (t--){
            scanf("%s", ch);
            n = strlen(ch);
            bool flag = true;
            for (int i = 0; i < n; i++){
                if ((i == 0 || i == n-1) && ch[i] > '4'){
                    flag = false; break;
                }
                if (ch[i] > '6'){
                    flag = false; break;
                }
                a[i + 1] = ch[i] - '0';
            }
            if (!flag) {
                printf("0
    "); continue;
            }
            printf("%I64d
    ", solve());
        }
        return 0;
    }
    View Code

    J.最大公约数

    严格来说做这题时这根本不是赛时状态。。。这题的题解有人放在async结果一不小心看到题解的一部分

    赛时还想着把数列切成3部分:以模结果为0为边界,然后就把自己搞死了

    其实此题同j不同i的数之间的差是循环节来的,就是说可以只切成2部分:前面每c[i][j]个数一组求和,用等差数列的方法算,后面n%c[i][j]个直接算,不用优化成o(1)

    组内公差不好处理,转组外公差就好解决,毕竟公差正好都是凑够不会被向下取整的整数,还相等

    时间复杂度o(t*m^2*log2n) c是辗转相除法次数,不超log2n

    #include <bits/stdc++.h>
    //#include<iostream>
    using namespace std;
    typedef double db;
    typedef long long ll;
    typedef unsigned int uint;
    typedef unsigned long long ull;
    const db eps=1e-6;
    const int N=700;
    #define lson l, m, rt << 1
    #define rson m + 1, r, rt << 1 | 1
    #define CLR(a, b) memset(a, b, sizeof(a))
    
    int gcd[N][N],c[N][N],f[N][N];
    int tmp[N];
    void calc(int a,int b)
    {
        int pc=0,x=a,y=b;
        while(y>0)
        {
            pc++;
            int t=x%y;
            x=y;
            y=t;
        }
        gcd[a][b]=x;
        c[a][b]=pc;
        f[a][b]=pc*x*x;
    }
    int main()
    {
        int t,i,j,n,m,p;
        memset(f,0,sizeof(f));
        for(i=1;i<700;i++)for(j=1;j<700;j++)calc(i,j);
        scanf("%d",&t);
        for(int h=0;h<t;h++)
        {
            scanf("%d%d%d",&n,&m,&p);
            ll ans=0;
            for(j=1;j<=m;j++)
            {
                for(i=1;i<=j;i++)
                {
                    ll a1=0;
                    for(int l=0;l<c[i][j];l++)//前c[i][j]个作为等差数列的第1项
                    {
                        tmp[l]=(i+j*l)*j/f[i][j]%p;
                        a1=(a1+tmp[l])%p;
                    }
                    ll cnt=(n-i)/j;cnt++;
                    ll num=cnt/c[i][j],g=gcd[i][j];
                    ll d=(j/g*j/g)%p*c[i][j]%p;//不要管组内公差,组外公差才容易处理。这是每c[i][j]个组合起来的结果
                    ans=(ans+num*(num-1)/2%p*d%p+num*a1%p)%p;
                    ll rem=cnt%c[i][j];
                    for(int k=0;k<rem;k++)ans=(ans+tmp[k]+num*j/g*j/g%p)%p;//第2部分
                }
            }
            printf("%I64d
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    C#中异步和多线程的区别
    猫 老鼠 人的编程题
    C#中数组、ArrayList和List三者的区别
    经典.net面试题目
    sql有几种删除表数据的方式
    内存池的实现
    A*算法为什么是最优的
    传教士与野人问题
    d3d导致cairo不正常
    c++中的signal机制
  • 原文地址:https://www.cnblogs.com/dgutfly/p/6043882.html
Copyright © 2011-2022 走看看