• 2016年中国大学生程序设计竞赛(合肥)-重现赛(感谢安徽大学)(5/10)


    1001: 传递要求 a->b->c && a->c

    我的做法就是利用bitset预处理出x点可达点集,与可达到x点的点集

    那么如何检验这个图是否传递;枚举完b和,枚举可达b点集中的点x,那么点x可达点集要包含c点集,这个利用bieset可以快速判断

    整个做法就是(n^2)

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<sstream>
    #include<algorithm>
    #include<vector>
    #include<bitset>
    #include<set>
    #include<queue>
    #include<stack>
    #include<map>
    #include<cstdlib>
    #include<cmath>
    #define PI 2*asin(1.0)
    #define LL long long
    #define pb push_back
    #define pa pair<int,int>
    #define clr(a,b) memset(a,b,sizeof(a))
    #define lson lr<<1,l,mid
    #define rson lr<<1|1,mid+1,r
    #define bug(x) printf("%d++++++++++++++++++++%d
    ",x,x)
    #define key_value ch[ch[root][1]][0]
    const int  MOD = 1000000007;
    const int N = 2016+15;
    const int maxn = 200+ 14;
    const int mm=100010;
    const int letter = 130;
    const int INF = 1e9;
    const double pi=acos(-1.0);
    const double eps=1e-8;
    using namespace std;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int T,n;
    char s[N][N];
    bitset<N>vs[2][N],tt;
    int main(){
        scanf("%d",&T);
        while(T--){
            scanf("%d",&n);
            for(int i=1;i<=n;i++) scanf("%s",s[i]+1);
            for(int i=1;i<=n;i++) vs[0][i].reset(),vs[1][i].reset();
            for(int i=1;i<=n;i++){
                for(int j=1;j<=n;j++){
                    if(s[i][j]=='P'){
                        vs[1][i][j]=vs[0][j][i]=1;
                    }
                }
            }
            int flag=1;
            for(int x=1;x<=n;x++){
                for(int i=1;i<=n;i++){
                    if(vs[0][x][i]){
                        tt=vs[1][i]&vs[1][x];
                        if(tt!=vs[1][x]){flag=0;break;}
                    }
                }
                if(!flag) break;
            }
            if(!flag){
                puts("N");
                continue;
            }
            for(int i=1;i<=n;i++) vs[0][i].reset(),vs[1][i].reset();
            for(int i=1;i<=n;i++){
                for(int j=1;j<=n;j++){
                    if(s[i][j]=='Q'){
                        vs[1][i][j]=vs[0][j][i]=1;
                    }
                }
            }
            flag=1;
            for(int x=1;x<=n;x++){
                for(int i=1;i<=n;i++){
                    if(vs[0][x][i]){
                        tt=vs[1][i]&vs[1][x];
                        if(tt!=vs[1][x]){flag=0;break;}
                    }
                }
                if(!flag) break;
            }
            if(flag) puts("T");
            else puts("N");
        }
        return 0;
    }
    1001

    1003:对于给定以x为根的游戏,我们把看看作是多条链的组合游戏(组合博弈)

    那么一条链怎么赢?

      我们以低位为接近根的边权:

        00001:先手必赢 ,000010:先手必败

        00011:先手必赢, 000100:先手必败………………

      找到规律接近根的地方为1,先手必赢,否则必败

      根据博弈组合游戏,那么答案就是包含x点的边权的异或和来判断先手是否能赢

    #include<bits/stdc++.h>
    using namespace std;
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define ls i<<1
    #define rs ls | 1
    #define mid ((ll+rr)>>1)
    #define pii pair<int,int>
    #define MP make_pair
    typedef long long ll;
    const long long INF = 1e18+1LL;
    const double Pi = acos(-1.0);
    const int N = 1e5+10, maxn = 1e3+20, inf = 2e9;
    struct edge
    {
        int v,w;
        int nex;
    }edge[N];
    int head[N];
    int edg;
    void init()
    {
        memset(head,-1,sizeof(head));
        edg=0;
    }
    void add(int u,int v,int w)
    {
        edg++;
        edge[edg].v=v;
        edge[edg].w=w;
        edge[edg].nex=head[u];
        head[u]=edg;
    }
    int main(){
        int T;
        scanf("%d",&T);
        while(T--)
        {
            init();
            int n,m;
            scanf("%d%d",&n,&m);
            for(int i=1;i<n;i++)
            {
                int u,v,w;
                scanf("%d%d%d",&u,&v,&w);
                add(u,v,w);
                add(v,u,w);
            }
            while(m--)
            {
                int hh;
                scanf("%d",&hh);
                if(hh==0)
                {
                    int x;
                    scanf("%d",&x);
                    int ANS=0;
                    for(int i=head[x];i!=-1;i=edge[i].nex)
                    {
                        int w=edge[i].w;
                        ANS^=w;
                    }
                    if(ANS)
                        printf("Girls win!
    ");
                    else
                        printf("Boys win!
    ");
                }
                else
                {
                    int u,v,w;
                    scanf("%d%d%d",&u,&v,&w);
                    for(int i=head[u];i!=-1;i=edge[i].nex)
                    {
                        if(edge[i].v==v)
                        {
                            edge[i].w=w;
                            break;
                        }
                    }
                    for(int i=head[v];i!=-1;i=edge[i].nex)
                    {
                        if(edge[i].v==u)
                        {
                            edge[i].w=w;
                            break;
                        }
                    }
                }
            }
        }
        return 0;
    }
    1003

    1005:

      假设我们确定了前两列的状态,那么整个行列就可以O(n)推出来了

      枚举状态就好了

     #include<bits/stdc++.h>
        using namespace std;
        #pragma comment(linker, "/STACK:102400000,102400000")
        #define ls i<<1
        #define rs ls | 1
        #define mid ((ll+rr)>>1)
        #define pii pair<int,int>
        #define MP make_pair
        typedef long long LL;
        const long long INF = 1e18+1LL;
        const double Pi = acos(-1.0);
        const int N = 1e4+10, maxn = 1e3+20, inf = 2e9;
        const LL mod = 100000000+7;
        int n;
        char a[N];
        int b[N];
        LL cc(int x){
            if(x==0||x==2) return 1ll;
            return 2ll;
        }
        int main(){
            int T;
            scanf("%d",&T);
            while(T--){
                scanf("%s",a);
                n=strlen(a);
                for(int i=0;i<n;i++) a[i]-='0';
                if(n==1){
                    if(a[0]==1) puts("2");
                    else if(a[0]==0||a[0]==2) puts("1");
                    else puts("0");
                    continue;
                }
                LL ans=0;
                for(int x=0;x<=min(2,(int)a[0]);x++){
                    ///printf("x = %d
    ",x);
                    LL sum=1;
                    if(a[0]-x>2||a[0]-x<0) continue;
                    b[0]=a[0]-x,b[1]=x;
                    sum=sum*cc(b[0])%mod,sum=sum*cc(b[1])%mod;
                    for(int i=2;i<n;i++){
                        b[i]=a[i-1]-b[i-1]-b[i-2];
                        if(b[i]<0||b[i]>2) {sum=0;break;}
                        sum=sum*cc(b[i])%mod;
                    }
                    if(b[n-1]+b[n-2]!=a[n-1]) sum=0;
                    ans=(ans+sum)%mod;
                    ///printf("%d %d sum = %lld
    ",a[0]-x,x,sum);
                }
                printf("%lld
    ",ans);
            }
            return 0;
        }
    1005

    1008:

      n只有100,预处理n^2出每段区间的异或和

      那么查询的时候就二分找最近的值

    #include<bits/stdc++.h>
    using namespace std;
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define ls i<<1
    #define rs ls | 1
    #define mid ((ll+rr)>>1)
    #define pii pair<int,int>
    #define MP make_pair
    typedef long long LL;
    const long long INF = 1e18+1LL;
    const double Pi = acos(-1.0);
    const int N = 1e5+10, maxn = 1e3+20, mod = 1e9+7, inf = 2e9;
    
    
    struct ss{
        int value,c;
    }mp[N];
    bool cmp(ss s1,ss s2) {
            if(s1.value == s2.value) return s1.c>s2.c;
            else return s1.value < s2.value;
    }
    int n,sum[N],a[N],cnt,san[N];
    map<int,int > H;
    int main() {
            int T;
            scanf("%d",&T);
            while(T--) {
                cnt = 0;
                scanf("%d",&n);
                H.clear();
                for(int i  =1; i<=n; ++i)
                    scanf("%d",&a[i]),sum[i]=sum[i-1]^a[i];
                for(int i = 1; i <= n; ++i) {
                    for(int j = i; j <= n; ++j) {
                        if(H[sum[j]^sum[i-1]]) {
                            mp[H[sum[j]^sum[i-1]]].c = max(j-i+1,mp[H[sum[j]^sum[i-1]]].c);
                        } else {
                            mp[++cnt].value = sum[j]^sum[i-1];
                            mp[cnt].c = j-i+1;
                            H[sum[j]^sum[i-1]] = cnt;
                        }
                    }
                }
                sort(mp+1,mp+cnt+1,cmp);
                for(int i = 1; i <= cnt; ++i) {
                    san[i] = mp[i].value;
                }
                int m,x;
                scanf("%d",&m);
                while(m--) {
                    scanf("%d",&x);
                    if(x <= san[1]) {
                        printf("%d
    ",mp[1].c);
                        continue;
                    }
                    if(x >= san[cnt]) {
                        printf("%d
    ",mp[cnt].c);
                        continue;
                    }
                    int pos1 = lower_bound(san+1,san+1+cnt,x) - san;
                    int pos2 = pos1-1;
                    if(abs(san[pos1]-x) < abs(san[pos2] - x)) {
                        printf("%d
    ",mp[pos1].c);
                    } else if(abs(san[pos1]-x) > abs(san[pos2] - x))
                        printf("%d
    ",mp[pos2].c);
                      else printf("%d
    ",max(mp[pos1].c,mp[pos2].c));
                }
                printf("
    ");
            }
            return 0;
    }
    1008

    1009:

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define pi (4*atan(1.0))
    #define eps 1e-14
    const int N=2e5+10,M=4e6+10,inf=1e9+10,mod=1e9+7;
    const ll INF=1e18+10;
    int a[110];
    ll check(ll x)
    {
        int sum=0;
        while(x)
        {
            sum++;
            x/=2;
        }
        return sum;
    }
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            ll l,r;
            scanf("%lld%lld",&l,&r);
            int L=check(l);
            int R=check(r);
            if(L!=R)
            {
                printf("%lld
    ",(1ll<<max(L,R))-1);
            }
            else
            {
                if(L==0) {
                    puts("0");
                    continue;
                }
                int ps=L-1;
                int cnt=0;
                while((l&(1ll<<ps))==(r&(1ll<<ps))&&ps>=0){
                    a[++cnt]=(l&(1ll<<ps))>>ps;
                    ps--;
                }
                for(int i=cnt+1;i<=L;i++) a[i]=1;
                ll ans=0;
                for(int i=1;i<=L;i++) ans=ans*2ll+1ll*a[i];
                printf("%lld
    ",ans);
            }
        }
        return 0;
    }
    1009
  • 相关阅读:
    pandas 分组过滤
    bert fine tuning方法
    对字典进行排序
    1*1的卷积的作用
    使用Conv代替全连接层FC
    训练笔记
    javascript 正则分组捕捉
    谷歌浏览器 喔唷,崩溃啦
    sed awk
    c# 通过程序修改hosts文件
  • 原文地址:https://www.cnblogs.com/zxhl/p/6033641.html
Copyright © 2020-2023  润新知