• 2017-7-14测试


    问题 A: 正确答案

    时间限制: 2 Sec  内存限制: 256 MB
    提交: 665  解决: 76
    [提交][状态][讨论版]

    题目描述

    小H与小Y刚刚参加完UOIP外卡组的初赛,就迫不及待的跑出考场对答案。

    “吔,我的答案和你都不一样!”,小Y说道,”我们去找神犇们问答案吧”。

    外卡组试卷中共有m道判断题,小H与小Y一共从其他n个神犇那问了答案。之后又从小G那里得知,这n个神犇中有p个考了满分,q个考了零分,其他神犇不为满分或零分。这可让小Y与小H犯了难。你能帮助他们还原出标准答案吗?如有多解则输出字典序最小的那个。无解输出-1。

    输入

    第一行四个整数n, m, p, q,意义如上描述。

    接下来n行,每一行m个字符’N’或’Y’,表示这题这个神犇的答案。

    输出

    仅一行,一个长度为m的字符串或是-1。

    样例输入

    2 2 2 0 YY YY

    样例输出

    YY

    提示

    "Times New Roman";mso-hansi-font-family:"Times New Roman"">【数据范围】

    30% : n <= 100.

    60% : n <= 5000 , m <= 100.

    100% : 1 <= n <= 30000 , 1 <= m <= 500. 0 <= p , q.  p + q <= n.

    此题思路很容易,但是c++我纠结于如何读入一个string类的字符串,pascal又不会手写map。最后发现其实c++可以直接用map标记string

    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<map>
    #include<cstring>
    #include<string>
    #include<queue>
    #include<algorithm>
    using namespace std;
    map<string,int>Z,F;
    map<string,int>::iterator it;
    int n,m,p,q,num;
        char ST[510],IST[510],ans[510];
    bool pl(){
        int point=m-1;
        while (ST[point]=='Y') {
            if (point==0) return false;
            ST[point]='N',point--;
        }
        ST[point]='Y';
        return true;
    }
    
    int main(){
        scanf("%d%d%d%d",&n,&m,&p,&q);
    
        for(int i=1;i<=n;i++){
            scanf("%s",ST);
            for(int j=0;j<m;j++)
                ST[j]=='Y'?IST[j]='N':IST[j]='Y';
            Z[ST]++;
            //cout<<IST<<endl;
            F[IST]++;
        }
        it=Z.begin();
        string st;
        string data;
        bool firstans=true;
        if ((p==0)&&(q==0)){
            for(int j=0;j<m;j++)ST[j]='N';
            do{
                //cout<<ST;
                if ((Z[ST]==0)&&(F[ST]==0)){
                    cout<<ST;
                    return 0;
                }
            }while(pl());
            cout<<-1;
            return 0;
        }
        while(it!=Z.end()){
            num=it->second;
            //printf("%d
    ",num);
            if (num!=p) {
                it++;
                continue;
            }
            st=it->first;
            //cout<<st<<en6dl;
            num=F[st];
            if (num!=q) {
                it++;
                continue;
            }
            if ((firstans)||(st<data))
                firstans=false,data=st;
            it++;
        }
        /*
        it=F.begin();
        while(it!=F.end()){
            num=it->second;
            if (num!=q) {
                it++;
                continue;
            }
            st=it->first;
            //cout<<st<<endl;
            num=Z[st];
            if (num!=p) {
                it++;
                continue;
            }
            if ((firstans)||(st<data))
                firstans=false,data=st;
            it++;
        }*/
        if (firstans) cout<<-1; else cout<<data;
    }
    View Code

    序列问题

    时间限制: 1 Sec  内存限制: 256 MB
    提交: 340  解决: 29
    [提交][状态][讨论版]

    题目描述

    小H是个善于思考的学生,她正在思考一个有关序列的问题。

    她的面前浮现出了一个长度为n的序列{ai},她想找出两个非空的集合S、T。

    这两个集合要满足以下的条件:

    1. 两个集合中的元素都为整数,且都在 [1, n] 里,即Si,Ti ∈ [1, n]。

    2. 对于集合S中任意一个元素x,集合T中任意一个元素y,满足x < y。

    3. 对于大小分别为p, q的集合S与T,满足

                a[s1] xor a[s2] xor a[s3] ... xor a[sp] = a[t1] and a[t2] and a[t3] ... and a[tq].

    小H想知道一共有多少对这样的集合(S,T),你能帮助她吗?

    输入

    第一行,一个整数n

           第二行,n个整数,代表ai。

    输出

    仅一行,表示最后的答案。

    样例输入

    4 1 2 3 3

    样例输出

    4

    提示

    【样例解释】

    S = {1,2}, T = {3}, 1 ^ 2 = 3 = 3 (^为异或)

    S = {1,2}, T = {4}, 1 ^ 2 = 3 = 3

    S = {1,2}, T = {3,4} 1 ^ 2 = 3 & 3 = 3 (&为与运算)

    S = {3}, T = {4} 3 = 3 = 3


    【数据范围】


        30%: 1 <= n <= 10


        60%: 1 <= n <= 100


        100%: 1 <= n <= 1000, 0 <= ai < 1024

    一开始以为爆搜能拿30分——开心,后来爆弹(气死了),后来发现hzw的搜索代码也是0分——开心。

    其实这道题的DP很好想。

    F[i][j]表示前i个数(第i个数一定要取)亦或值为j的方案数。

    但这样转移的时候要同时枚举j,k。时间复杂度n^2*1024;

    其实我们可以加个辅助数组,f[i][j]表示前i个数(第i个数不一定要取的方案数)这样就可以直接转移啦。(其实求答案时的时间复杂度还是n^2*1024);

    最后这道题要开高精度+压位

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #define maxn 1110
    #define ll long long 
    using namespace std;
    ll f[maxn][maxn],F[maxn][maxn],g[maxn][maxn],G[maxn][maxn],n,a[maxn],ans;
    int main()
    {
        scanf("%lld",&n);
        for(ll i=1;i<=n;i++)
        scanf("%lld",&a[i]);
        //f[i] means the number of ways to choose  when i needn't to be choosen but F[i] means i must to be choosen
        //g is same as f
        for(ll i=1;i<=n;i++)
        {
            f[i][a[i]]++;
            F[i][a[i]]++;
            for(ll k=0;k<1024;k++)
                f[i][k]+=f[i-1][k];
            for(ll k=0;k<1024;k++)
                f[i][a[i]^k]+=f[i-1][k],F[i][a[i]^k]+=f[i-1][k];
        }
        for(ll i=n;i>=1;i--)
        {
            g[i][a[i]]++;
            G[i][a[i]]++;
            for(ll k=0;k<1024;k++)
                g[i][k]+=g[i+1][k];
            for(ll k=0;k<1024;k++)
                 g[i][a[i]&k]+=g[i+1][k],G[i][a[i]&k]+=g[i+1][k];    
        }
        for(ll i=1;i<=n;i++)
            for(ll k=i+1;k<=n;k++)
            //if(a[i]<a[k])
            {
                for(ll j=0;j<1024;j++)
                ans+=F[i][j]*G[k][j];
            }
        printf("%lld
    ",ans);    
        
    }

    问题 C: 长途旅行

    时间限制: 1 Sec  内存限制: 256 MB
    提交: 285  解决: 48
    [提交][状态][讨论版]

    题目描述

    JY是一个爱旅游的探险家,也是一名强迫症患者。现在JY想要在C国进行一次长途旅行,C国拥有n个城市(编号为0,1,2...,n - 1),城市之间有m条道路,可能某个城市到自己有一条道路,也有可能两个城市之间有多条道路,通过每条道路都要花费一些时间。JY从0号城市开始出发,目的地为n – 1号城市。由于JY想要好好参观一下C国,所以JY想要旅行恰好T小时。为了让自己的旅行更有意思,JY决定不在任何一个时刻停留(走一条到城市自己的路并不算停留)。JY想知道是否能够花恰好T小时到达n – 1号城市(每个城市可经过多次)。现在这个问题交给了你。

    若可以恰好到达输出“Possible”否则输出“Impossible”。(不含引号)。

    输入

    第一行一个正整数Case,表示数据组数。

           每组数据第一行3个整数,分别为n, m, T。

           接下来m行,每行3个整数x, y, z,代表城市x和城市y之间有一条耗时为z的双向边。

    输出

    对于每组数据输出”Possible”或者”Impossible”.

    样例输入

    2
    3 3 11
    0 2 7
    0 1 6
    1 2 5
    2 1 10000
    1 0 1
    

    样例输出

    Possible
    Impossible
    

    提示

           30%:  T <= 10000


    另有30%: n <= 5 , m <= 10 , Case <= 5.


           100%: 2 <= n <= 50, 1 <= m <= 100, 1 <= z <= 10000, 1 <= T <= 10^18, Case <= 15.

    这道题考试的时候想到了用f[i][j]表示到达i点用j时间的可行性,但是T实在太大。因为出发点肯定连着至少一条边。因为T很大,所以必定有很多浪费的时间(即去一个已经走过的城市),我们把这些浪费的时间全部用在走与原点相邻的一条边上(走来走去),然后可以发现只要是这条边长*2的整数倍的时间都可以浪费掉。令dis[i][j]表示到达第i个点,所花的总时间模上两倍的第一条边的边长是j时的最少花费时间。

    比较感性的理解一下就是到达第i个点的时间如果比T大或者=NIL,就不行。如果存在一种方案使得花费时间%2*p=T%2p且小于T,就可以走到了

    hgz的代码

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    #include <queue>
    
    using namespace std;
    typedef long long ll;
    
    struct PATH
    {
        int dis, to;
    };
    
    struct NODE
    {
        int s, t;
    };
    
    vector<PATH> path[1010];
    
    ll dis[55][20005];
    int cnt, s, k, a, b, c, n, m, i, mod, t;
    ll T;
    void spfa()
    {
        memset(dis, 0x7f7f7f7f, sizeof(dis));
        Queue<NODE> Q1;
        Q1.push((NODE){s, 0});
        dis[s][0] = 0;
        while (!Q1.empty())
        {
            NODE tmp = Q1.front();
            Q1.pop();
            int u = tmp.s;
            for (int i = 0; i < path[u].size(); i++)
            {
                int goton = path[u][i].to;  
                int t2 = (tmp.t + path[u][i].dis) % mod;
                if (dis[goton][t2] > dis[u][tmp.t] + path[u][i].dis)
                {
                    dis[goton][t2]=dis[u][tmp.t]+path[u][i].dis;
                    Q1.push((NODE){goton,t2});
                }
            }
        }
    }
    
    void addpath(int a, int b, int c)
    {
        PATH tmp;
        tmp.to = b;
        tmp.dis = c;
        path[a].push_back(tmp);
        if ((a == 1) && (c < mod))
            mod = c;
    }
    
    int main()
    {
        scanf("%d", &t);
        while (t--)
        {
            for (int i = 1; i <= n; i++)
            {
                path[i].clear();
            }
            mod = 0x7f7f7f7f;
            scanf("%d%d%lld", &n, &m, &T);
            for (int i = 1; i <= m; i++)
            {
                scanf("%d%d%d", &a, &b, &c);
                a++, b++;
                addpath(a, b, c);
                addpath(b, a, c);
            }
            if (mod == 0x7f7f7f7f)
                printf("Impossible
    ");
            else
            {
                mod *= 2;
                s = 1;
                spfa();
                if (dis[n][T % mod] <= T)
                    printf("Possible
    ");
                else
                    printf("Impossible
    ");
            }
        }
        system("pause");
        return 0;
    }
  • 相关阅读:
    杜教筛瞎扯
    网络流 24 题 解题报告
    多项式重工业修炼日志
    c#与js中10进制16进制的转化,记录防忘
    如何在RichTextBox中改变多个字符串的颜色以及字体
    C#TreeView控件遍历文件夹下所有子文件夹以及文件
    自己用c语言实现字符串处理库函数以及扩展
    gcc for windows(mingw)编译多个c文件
    迪杰斯特拉(dijkstra)算法的简要理解和c语言实现(源码)
    spring web mvc中遇到的错误以及学习小记(持续记录)
  • 原文地址:https://www.cnblogs.com/dancer16/p/7182249.html
Copyright © 2020-2023  润新知