zoukankan      html  css  js  c++  java
  • cf Round 633

    A.Rebus(思维题)

    给出一个这种形式的表达式 ? + ? - ? + ? = n.
    要求用1-n的数字填充疑问号使等式成立,如果不存在这样的方式,则输出不可能。
    存在则输出任意的方式。

    移项可以变成?+?+?...=n+?+?+...的形式,可以求出等式左边和右边的取值范围,如果不相交则无解,然后贪心构造一下即可。

    # include <stdio.h>
    # include <string.h>
    # include <stdlib.h>
    # include <iostream>
    # include <vector>
    # include <queue>
    # include <stack>
    # include <map>
    # include <math.h>
    # include <algorithm>
    using namespace std;
    # define lowbit(x) ((x)&(-x))
    # define pi acos(-1.0)
    # define MAXN 10005
    # define eps 1e-5
    # define MAXM 1000005
    # define MOD 1000000007
    # define INF 1000000000
    # define mem(a,b) memset(a,b,sizeof(a))
    # define FOR(i,a,n) for(int i=a; i<=n; ++i)
    # define FO(i,a,n) for(int i=a; i<n; ++i)
    # define bug puts("H");
    # define lch p<<1,l,mid
    # define rch p<<1|1,mid+1,r
    # pragma comment(linker, "/STACK:1024000000,1024000000")
    typedef long long LL;
    typedef unsigned long long ULL;
    int _MAX(int a, int b){return a>b?a:b;}
    int _MIN(int a, int b){return a>b?b:a;}
    int Scan() {
        int res=0, flag=0;
        char ch;
        if((ch=getchar())=='-') flag=1;
        else if(ch>='0'&&ch<='9') res=ch-'0';
        while((ch=getchar())>='0'&&ch<='9')  res=res*10+(ch-'0');
        return flag?-res:res;
    }
    void Out(int a) {
        if(a<0) {putchar('-'); a=-a;}
        if(a>=10) Out(a/10);
        putchar(a%10+'0');
    }
    
    char s[500];
    int vis[500], cnt=0, ans[500];
    
    int main()
    {
        int p, fu=0, zheng=1, n=0;
        gets(s);
        vis[0]=1;
        for (int i=2; ; i+=4) {
            if (s[i]=='=') {p=i; break;}
            else if (s[i]=='+') vis[++cnt]=1, zheng++;
            else if (s[i]=='-') vis[++cnt]=-1, fu++;
        }
        for (int i=p+2; s[i]; ++i) n=n*10+s[i]-'0';
        if (n*zheng<n+fu||n+fu*n<zheng) puts("Impossible");
        else {
            puts("Possible");
            if (n*zheng>=n+fu&&n+fu>=zheng) {
                int mod=(n+fu)%zheng;
                for (int i=0; i<=cnt; ++i) {
                    if (vis[i]==-1) ans[i]=1;
                    else {
                        ans[i]=(n+fu)/zheng;
                        if (mod) ans[i]++, mod--;
                    }
                }
            }
            else {
                int mod=(zheng-n)%fu;
                for (int i=0; i<=cnt; ++i) {
                    if (vis[i]==1) ans[i]=1;
                    else {
                        ans[i]=(zheng-n)/fu;
                        if (mod) ans[i]++, mod--;
                    }
                }
            }
            for (int i=0; i<=cnt; ++i) {
                    if (i) printf(vis[i]==1?"+ ":"- ");
                    printf("%d ",ans[i]);
                }
                printf("= %d
    ",n);
        }
        return 0;
    }
    View Code

    B.International Olympiad(思维题)

     

    题意:给出每次奥林匹克的缩写,第一次是1989年,缩写为9,每次不能重复,
    问给出n个询问,每个询问是一个缩写,问真实的年份是多少。

     

    我们观察发现
    1989-1998 占了个位数的全部
    1999-2098 占了十位数的全部
    2099-3098 占了百位数的全部
    3099-13098 占了万位数的全部

     

    于是我们可以找出规律,直接搞就行了。

    # include <stdio.h>
    # include <string.h>
    # include <stdlib.h>
    # include <iostream>
    # include <vector>
    # include <queue>
    # include <stack>
    # include <map>
    # include <math.h>
    # include <algorithm>
    using namespace std;
    # define lowbit(x) ((x)&(-x))
    # define pi acos(-1.0)
    # define MAXN 10005
    # define eps 1e-5
    # define MAXM 1000005
    # define MOD 1000000007
    # define INF 1000000000
    # define mem(a,b) memset(a,b,sizeof(a))
    # define FOR(i,a,n) for(int i=a; i<=n; ++i)
    # define FO(i,a,n) for(int i=a; i<n; ++i)
    # define bug puts("H");
    # define lch p<<1,l,mid
    # define rch p<<1|1,mid+1,r
    # pragma comment(linker, "/STACK:1024000000,1024000000")
    typedef long long LL;
    typedef unsigned long long ULL;
    int _MAX(int a, int b){return a>b?a:b;}
    int _MIN(int a, int b){return a>b?b:a;}
    int Scan() {
        int res=0, flag=0;
        char ch;
        if((ch=getchar())=='-') flag=1;
        else if(ch>='0'&&ch<='9') res=ch-'0';
        while((ch=getchar())>='0'&&ch<='9')  res=res*10+(ch-'0');
        return flag?-res:res;
    }
    void Out(int a) {
        if(a<0) {putchar('-'); a=-a;}
        if(a>=10) Out(a/10);
        putchar(a%10+'0');
    }
    
    char s[15];
    
    int main ()
    {
        int n;
        scanf("%d",&n);
        while (n--) {
            scanf("%s",s);
            int len=strlen(s+4), year=atoi(s+4), F=0, ten=10;
            FO(i,1,len) {
                F+=ten;
                ten*=10;
            }
            while (year<1989+F) year+=ten;
            printf("%d
    ",year);
        }
        return 0;
    }
    View Code

     

    C.Graph Coloring(二分图染色)

    给出n个顶点,m条边的无向图(n,m<=1e5).
    初始时每条边有一种颜色R或者B。
    每操作一次可以选定一个点,并将该点邻接的边颜色全都取反,问至少需要多少次这样的操作可以将所有的边变成一种颜色。
    如果不存在输出-1.

    分析:
    分为两种情况,要么最后边都是R,要么都是B
    假设最后都会变成R,我们发现对于任意一个边(u,v),
    如果边uv是R,那么u,v都需要操作一次,或者都不需要操作。
    因为每一个顶点操作两次是没有必要的,所以我们可以发现对于每个顶点,要么不操作,要么操作一次。
    于是我们可以把它们按操作数是否相等划分到S-T集合里面去,如果边uv是R,则u,v属于同一集合。如果边uv是B,则u,v属于不同的集合。
    最后的答案就是S和T集合模的最小值。

    如果图不连通,我们可以对他的强连通分量做。
    于是问题就转化成了二分图染色了

    # include <stdio.h>
    # include <string.h>
    # include <stdlib.h>
    # include <iostream>
    # include <vector>
    # include <queue>
    # include <stack>
    # include <map>
    # include <math.h>
    # include <algorithm>
    using namespace std;
    # define lowbit(x) ((x)&(-x))
    # define pi acos(-1.0)
    # define MAXN 100005
    # define eps 1e-5
    # define MAXM 1000005
    # define MOD 1000000007
    # define INF 1000000000
    # define mem(a,b) memset(a,b,sizeof(a))
    # define FOR(i,a,n) for(int i=a; i<=n; ++i)
    # define FO(i,a,n) for(int i=a; i<n; ++i)
    # define bug puts("H");
    # define lch p<<1,l,mid
    # define rch p<<1|1,mid+1,r
    # pragma comment(linker, "/STACK:1024000000,1024000000")
    typedef long long LL;
    typedef unsigned long long ULL;
    int _MAX(int a, int b){return a>b?a:b;}
    int _MIN(int a, int b){return a>b?b:a;}
    int Scan() {
        int res=0, flag=0;
        char ch;
        if((ch=getchar())=='-') flag=1;
        else if(ch>='0'&&ch<='9') res=ch-'0';
        while((ch=getchar())>='0'&&ch<='9')  res=res*10+(ch-'0');
        return flag?-res:res;
    }
    void Out(int a) {
        if(a<0) {putchar('-'); a=-a;}
        if(a>=10) Out(a/10);
        putchar(a%10+'0');
    }
    
    struct Edge{int p, next, flag;}edge[MAXN<<1];
    int head[MAXN], set[MAXN], cnt=1, ans1[MAXN], ans2[MAXN], num1, num2, node[MAXN], vis[MAXN];
    int one, two;
    
    void add_edge(int u, int v, char flag)
    {
        int x=(flag=='R'?1:-1);
        edge[cnt].p=v; edge[cnt].next=head[u]; edge[cnt].flag=x; head[u]=cnt++;
        edge[cnt].p=u; edge[cnt].next=head[v]; edge[cnt].flag=x; head[v]=cnt++;
    }
    int find(int x)
    {
        int s, temp;
        for (s=x; set[s]>=0; s=set[s]) ;
        while (s!=x) temp=set[x], set[x]=s, x=temp;
        return s;
    }
    void union_set(int x, int y)
    {
        int temp=set[x]+set[y];
        if (set[x]>set[y]) set[x]=y, set[y]=temp;
        else set[y]=x, set[x]=temp;
    }
    bool dfs(int x, int mark)
    {
        for (int i=head[x]; i; i=edge[i].next) {
            int v=edge[i].p;
            if (node[v]) {
                if (mark==edge[i].flag&&node[v]!=node[x]) return false;
                if (mark!=edge[i].flag&&node[v]==node[x]) return false;
                continue;
            }
            node[v]=(mark==edge[i].flag?node[x]:-node[x]);
            node[v]==1?one++:two++;
            if (dfs(v,mark)==0) return false;
        }
        return true;
    }
    void find1(int x, int flag)
    {
        vis[x]=1;
        if (node[x]==flag) ans1[++num1]=x;
        for (int i=head[x]; i; i=edge[i].next) {
            int v=edge[i].p;
            if (vis[v]) continue;
            find1(v,flag);
        }
    }
    void find2(int x, int flag)
    {
        vis[x]=1;
        if (node[x]==flag) ans2[++num2]=x;
        for (int i=head[x]; i; i=edge[i].next) {
            int v=edge[i].p;
            if (vis[v]) continue;
            find2(v,flag);
        }
    }
    int main ()
    {
        int n, m, u, v;
        int flag1=1, flag2=1;
        scanf("%d%d",&n,&m);
        char s[3];
        mem(set,-1);
        while (m--) {
            scanf("%d%d%s",&u,&v,s);
            add_edge(u,v,s[0]);
            u=find(u); v=find(v);
            if (u!=v) union_set(u,v);
        }
        FOR(i,1,n) {
            if (set[i]<0) {
                node[i]=1; one=1, two=0;
                if (dfs(i,1)==0) {flag1=0; break;}
                if (one>two) find1(i,-1);
                else find1(i,1);
            }
        }
        mem(vis,0); mem(node,0);
        FOR(i,1,n) {
            if (set[i]<0) {
                node[i]=-1; one=0, two=1;
                if (dfs(i,-1)==0) {flag2=0; break;}
                if (one>two) find2(i,-1);
                else find2(i,1);
            }
        }
        if (flag1==0 && flag2==0) {puts("-1"); return 0;}
        if (flag1==0) num1=INF;
        else if (flag2==0) num2=INF;
        if (num1>num2) {
            printf("%d
    ",num2);
            FOR(i,1,num2) printf("%d ",ans2[i]);
            putchar('
    ');
        }
        else {
            printf("%d
    ",num1);
            FOR(i,1,num1) printf("%d ",ans1[i]);
            putchar('
    ');
        }
        return 0;
    }
    View Code

     

    D.To Hack or not to Hack(枚举+DP)

    显然可以hack的题数超过90时一定是第一名。
    否则我们可以枚举每道题的基本分,确定好每题最多能hack多少人。从而可以确定我们的最终分数。
    基本分一定时,hack人数当然越多越好。
    令dp[i][a][b][c]表示前i个人A题hack了a次,B题hack了b次,C题hack了c次的最高排名。
    若不能hack,或分数较少,则直接转移。否则枚举每题的hack状态进行转移即可。
    复杂度O(6^3*(n+90*30^3*2^3))

    # include <stdio.h>
    # include <string.h>
    # include <stdlib.h>
    # include <iostream>
    # include <vector>
    # include <queue>
    # include <stack>
    # include <map>
    # include <math.h>
    # include <algorithm>
    using namespace std;
    # define lowbit(x) ((x)&(-x))
    # define pi acos(-1.0)
    # define MAXN 100005
    # define eps 1e-5
    # define MAXM 1000005
    # define MOD 1000000007
    # define INF 1000000000
    # define mem(a,b) memset(a,b,sizeof(a))
    # define FOR(i,a,n) for(int (i)=(a); (i)<=(n); ++(i))
    # define FO(i,a,n) for(int (i)=(a); (i)<(n); ++(i))
    # define bug puts("H");
    # define lch p<<1,l,mid
    # define rch p<<1|1,mid+1,r
    # pragma comment(linker, "/STACK:1024000000,1024000000")
    typedef long long LL;
    typedef unsigned long long ULL;
    int _MAX(int a, int b){return a>b?a:b;}
    int _MIN(int a, int b){return a>b?b:a;}
    int Scan() {
        int res=0, flag=0;
        char ch;
        if((ch=getchar())=='-') flag=1;
        else if(ch>='0'&&ch<='9') res=ch-'0';
        while((ch=getchar())>='0'&&ch<='9')  res=res*10+(ch-'0');
        return flag?-res:res;
    }
    void Out(int a) {
        if(a<0) {putchar('-'); a=-a;}
        if(a>=10) Out(a/10);
        putchar(a%10+'0');
    }
    
    int n, a[5005][3], sum[3], hack[3], cnt, dp[2][95][95][95], sco[6][2];
    
    int cal(int x, int y, int z)
    {
        if (sco[x][0]>sco[x][1]||sco[y][0]>sco[y][1]||sco[z][0]>sco[z][1]) return n-1;
        if (sum[0]-hack[0]>sco[x][1]||sum[1]-hack[1]>sco[y][1]||sum[2]-hack[2]>sco[z][1]) return n-1;
        if (sum[0]<sco[x][0]||sum[1]<sco[y][0]||sum[2]<sco[z][0]) return n-1;
        int h1=min(sum[0]-sco[x][0], hack[0]);
        int h2=min(sum[1]-sco[y][0], hack[1]);
        int h3=min(sum[2]-sco[z][0], hack[2]);
        int mysco=(h1+h2+h3)*100+(a[1][0]!=0)*(x+1)*500*(250-abs(a[1][0]))/250+(a[1][1]!=0)*(y+1)*500*(250-abs(a[1][1]))/250+(a[1][2]!=0)*(z+1)*500*(250-abs(a[1][2]))/250;
        int flag=0, tot=0;
        FOR(i,0,h1) FOR(j,0,h2) FOR(k,0,h3) dp[0][i][j][k]=INF;
        dp[0][0][0][0]=0;
        FOR(i,2,n) {
            int hesco=(a[i][0]!=0)*(x+1)*500*(250-abs(a[i][0]))/250+(a[i][1]!=0)*(y+1)*500*(250-abs(a[i][1]))/250+(a[i][2]!=0)*(z+1)*500*(250-abs(a[i][2]))/250;
            if (a[i][0]>=0&&a[i][1]>=0&&a[i][2]>=0) {
                if (hesco>mysco) tot++;
                continue;
            }
            else if (hesco<=mysco) continue;
            int wei=0;
            FOR(j,0,2) {
                if (a[i][j]<0) wei=wei*2+1;
                else wei<<=1;
            }
            FOR(q1,0,h1) FOR(q2,0,h2) FOR(q3,0,h3) dp[flag^1][q1][q2][q3]=INF;
            FOR(q1,0,h1) FOR(q2,0,h2) FOR(q3,0,h3) {
                if (dp[flag][q1][q2][q3]>n) continue;
                FOR(j,0,(wei>>2)&1) FOR(k,0,(wei>>1)&1) FOR(l,0,wei&1) {
                    int shesco=(j==0&&a[i][0])*(x+1)*500*(250-abs(a[i][0]))/250+(k==0&&a[i][1])*(y+1)*500*(250-abs(a[i][1]))/250+(l==0&&a[i][2])*(z+1)*500*(250-abs(a[i][2]))/250;
                    if (shesco>mysco) dp[flag^1][q1+j][q2+k][q3+l]=min(dp[flag^1][q1+j][q2+k][q3+l], dp[flag][q1][q2][q3]+1);
                    else dp[flag^1][q1+j][q2+k][q3+l]=min(dp[flag^1][q1+j][q2+k][q3+l], dp[flag][q1][q2][q3]);
                }
            }
            flag^=1;
        }
        int ans=INF;
        FOR(i,0,h1) FOR(j,0,h2) FOR(k,0,h3) ans=min(ans, dp[flag][i][j][k]);
        return ans+tot;
    }
    int main ()
    {
        scanf("%d",&n);
        FOR(i,1,n) {
            scanf("%d%d%d",&a[i][0],&a[i][1],&a[i][2]);
            FOR(j,0,2) sum[j]+=(a[i][j]!=0);
            if(i!=1) FOR(j,0,2) hack[j]+=(a[i][j]<0);
        }
        // 特判
        if (hack[1]+hack[2]+hack[0]>=90) {puts("1"); return 0;}
        // 每个范围的分数
        int P=1;
        FOR(i,0,4) sco[i][0]=n/(2*P)+1, sco[i][1]=n/P, P*=2;
        sco[5][0]=0, sco[5][1]=n/32;
        int ans=INF;
        FOR(i,0,5) FOR(j,0,5) FOR(k,0,5) ans=min(ans,cal(i,j,k));
        printf("%d
    ",ans+1);
        return 0;
    }
    View Code

     

    E.Binary Table(待填坑)

  • 相关阅读:
    iOS7中修改StatusBar的显示颜色
    制作自己的字库并在工程中显示
    用字典给Model赋值并支持map键值替换
    用字典给Model赋值
    通过runtime打印出对象所有属性的值
    加密解密再也不是你的噩梦
    通过runtime获取对象相关信息
    UITableView的UITableViewStyleGrouped
    笑话
    【转】 ios开发证书CER文件、P12文件,mobileprovition许可文件的用途
  • 原文地址:https://www.cnblogs.com/lishiyao/p/6254365.html
Copyright © 2011-2022 走看看