zoukankan      html  css  js  c++  java
  • 【纪中受难记】——C3D7: 卡手题

    有点,力不从心?


    Description

    小H与小Y刚刚参加完UOIP外卡组的初赛,就迫不及待的跑出考场对答案。
    “吔,我的答案和你都不一样!”,小Y说道,”我们去找神犇们问答案吧”。
    外卡组试卷中共有m道判断题,小H与小Y一共从其他n个神犇那问了答案。之后又从小G那里得知,这n个神犇中有p个考了满分,q个考了零分,其他神犇不为满分或零分。这可让小Y与小H犯了难。你能帮助他们还原出标准答案吗?如有多解则输出字典序最小的那个。无解输出-1。
     

    Input

    第一行四个整数n, m, p, q,意义如上描述。
    接下来n行,每一行m个字符’N’或’Y’,表示这题这个神犇的答案。

    Output

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

    Sample Input

    2 2 2 0
    YY
    YY

    Sample Output

    YY
     

    Data Constraint

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

    考虑几种情况:

    1. p,q均不为0:可以一个个查询字符串满足pq条件,取最小值。

    2,p为0,q不为0或者pq都为0时,考虑未出现在给定字符串中的字符,即从最小字符开始往上枚举,找到可行解为止。

    3.只有q为0时,和1类似。

    推荐用哈希,我用的是multiset,t掉了

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #pragma GCC optimize(2)
      4 int read(){
      5     int x=0,f=1;
      6     char c=getchar();
      7     while(!isdigit(c)){
      8         if(c=='-') f=-1;
      9         c=getchar();
     10     }
     11     while(isdigit(c)){
     12         x=(x<<1)+(x<<3)+(c^48);
     13         c=getchar();
     14     }
     15     return x*f;
     16 }
     17 const int N=30010;
     18 int n,m,full,zero;
     19 multiset<string> q;
     20 string s[N];
     21 string ans;
     22 string rev(string t){
     23     for(int i=0;i<t.size();i++){
     24         if(t[i]=='N') t[i]='Y';
     25         else t[i]='N';
     26     }
     27     return t;
     28 }
     29 int main(){
     30     n=read();m=read();full=read();zero=read();
     31     if(full==0&&zero!=0){
     32         for(int i=1;i<=n;i++){
     33             cin>>s[i];
     34             q.insert(s[i]);
     35         }
     36         ans.assign(s[1]);
     37         for(int i=0;i<m;i++){
     38             ans[i]='N';
     39         }
     40         while(!(q.count(ans)==0&&q.count(rev(ans))==zero)){
     41             int i;
     42             for(i=m-1;i>=0;i--){
     43                 if(ans[i]=='N'){
     44                     ans[i]='Y';
     45                     break;
     46                 }
     47                 else ans[i]='N';
     48             }
     49             if(i==0){
     50                 printf("-1");
     51                 return 0;
     52             }
     53         }
     54         cout<<ans;
     55     }
     56     else if(full!=0&&zero==0){
     57         for(int i=1;i<=n;i++){
     58             cin>>s[i];
     59             q.insert(s[i]);
     60         }
     61         ans.assign(s[1]);
     62         for(int i=0;i<m;i++){
     63             ans[i]='Y';
     64         }
     65         sort(s+1,s+n+1);
     66         int siz=unique(s+1,s+n+1)-s-1;
     67         int flag=0;
     68         for(int i=1;i<=siz;i++){
     69             if(q.count(s[i])==full&&q.find(rev(s[i]))==q.end()){
     70                 ans=min(ans,s[i]);
     71                 flag=1;
     72             }
     73         }
     74         if(!flag){
     75             printf("-1");
     76         }
     77         else cout<<ans;
     78     }
     79     else if(full==0&&zero==0){
     80         for(int i=1;i<=n;i++){
     81             cin>>s[i];
     82             q.insert(s[i]);
     83         }
     84         ans.assign(s[1]);
     85         for(int i=0;i<m;i++){
     86             ans[i]='N';
     87         }
     88         while(q.count(ans)!=0||q.count(rev(ans))!=0){
     89             int i;
     90             for(i=m-1;i>=0;i--){
     91                 if(ans[i]=='N'){
     92                     ans[i]='Y';
     93                     break;
     94                 }
     95                 else ans[i]='N';
     96             }
     97             if(i==0){
     98                 printf("-1");
     99                 return 0;
    100             }
    101         }
    102         cout<<ans;
    103     }
    104     else{
    105         for(int i=1;i<=n;i++){
    106             cin>>s[i];
    107             q.insert(s[i]);
    108         }
    109         ans.assign(s[1]);
    110         for(int i=0;i<m;i++){
    111             ans[i]='Y';
    112         }
    113         sort(s+1,s+n+1);
    114         int siz=unique(s+1,s+n+1)-s-1;
    115         int flag=0;
    116         for(int i=1;i<=siz;i++){
    117             if(q.count(s[i])==full&&q.count(rev(s[i]))==zero){
    118                 ans=min(ans,s[i]);
    119                 flag=1;
    120             }
    121         }
    122         if(!flag){
    123             printf("-1");
    124         }
    125         else cout<<ans;
    126     }
    127     return 0;
    128 }
    129 //find =end no
    130 //

    Description

    小H是个善于思考的学生,她正在思考一个有关序列的问题。
    她的面前浮现出了一个长度为n的序列{ai},她想找出两个非空的集合S、T。
    这两个集合要满足以下的条件:
    两个集合中的元素都为整数,且都在 [1, n] 里,即Si,Ti ∈ [1, n]。
    对于集合S中任意一个元素x,集合T中任意一个元素y,满足x < y。
    对于大小分别为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),你能帮助她吗?
     

    Input

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

    Output

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

    Sample Input


    1 2 3 3

    Sample Output

    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 
     

    Data Constraint

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

    首先看到题目没有其他方法解,可以考虑dp。

    发现&和^有个区别:

    a^b=c能得到a^c=b,调换等式成立,而a&b=c不能得到a&c=b,这启发我们结论具有单向性。

    因此考虑从&到^处理。

    用f[i][j][0/1/2]表示以i点为界,1~i组成s序列,i+1~n组成t序列的方案数,0/1/2分别表示这个点不选/给s/给t

    那么转移式子有三个:

    f[i][j][0]=f[i+1][j][0];

    f[i][j][1]=f[i+1][j][0]+f[i+1][j][1]+f[i+1][j&a[i+1]][1];

    f[i][j][2]=f[i+1][j^a[i+1]][2]+f[i+1][j][1]+f[i+1][j][2];

    考虑and的性质,如果给个0给他,那么后面都是0了,因此要给所有位置附上1,由于数据范围<=1024,那就给1023吧。

    fp[0][1023][0]=1;

    就可以dp了。

    代码一开始用vector写的,后来t了。

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 int read(){
      4     int x=0,f=1;
      5     char c=getchar();
      6     while(!isdigit(c)){
      7         if(c=='-') f=-1;
      8         c=getchar();
      9     }
     10     while(isdigit(c)){
     11         x=(x<<1)+(x<<3)+(c^48);
     12         c=getchar();
     13     }
     14     return x*f;
     15 }
     16 const int N=2e3+10;
     17 const int W=1e9;
     18 //struct bigint{
     19 //    vector<int> s;
     20 //    bigint(long long a=0){
     21 //        *this=a;
     22 //    }
     23 //    bigint operator =(long long a){
     24 //        s.clear();
     25 //        while(a){
     26 //            s.push_back(a%mod);
     27 //            a/=mod;
     28 //        }
     29 //        return *this;
     30 //    }
     31 //    bigint operator +(bigint &b){
     32 //        bigint c;
     33 //        c.s.clear();
     34 //        for(int i=0,g=0;;i++){
     35 //            if(g==0&&i>=s.size()&&i>=b.s.size()) break;
     36 //            int x=g;
     37 //            if(i<s.size()) x+=s[i];
     38 //            if(i<b.s.size()) x+=b.s[i];
     39 //            c.s.push_back(x%mod);
     40 //            g=x/mod;
     41 //        }
     42 //        return c;
     43 //    }
     44 //    void print(){
     45 //        for(int i=s.size()-1;i>=0;i--){
     46 //            printf("%d",s[i]);
     47 //        }
     48 //    }
     49 //}f[2][N][3];
     50 struct node{
     51     int len,a[40];
     52     node():len(1){memset(a,0,sizeof(a));}
     53     inline void operator+=(node &b)
     54     {
     55         b.len>len?len=b.len:0;
     56         for (int i=1;i<=len;i++) {
     57             a[i]+=b.a[i];
     58             if (a[i]>=W) a[i+1]++,a[i]-=W;
     59         }
     60         if (a[len+1])len++;
     61         return ;
     62     }
     63     inline void print()
     64     {
     65         printf("%d",a[len]);
     66         for (int i=len-1;i;i--)
     67             printf("%09d",a[i]);
     68         return;
     69     }
     70 }f[2][1025][3];
     71 int n;
     72 int p[N];
     73 int main(){
     74     n=read();
     75     for(int i=n;i>=1;i--) p[i]=read();
     76     f[0][1023][0].a[1]=1;
     77 //    for(int i=0;i<n;i++){
     78 //        for(int j=0;j<=1023;j++){
     79 //            for(int k=0;k<=2;k++){
     80 //                f[p][j][k]=f[p^1][j][k];
     81 //            }
     82 //        }
     83 //        for(int j=0;j<=1023;j++){
     84 //            f[p][j&a[i+1]][1]=f[p][j&a[i+1]][1]+f[p^1][j][1]+f[p^1][j][0];
     85 //            f[p][j^a[i+1]][2]=f[p][j^a[i+1]][2]+f[p^1][j][1]+f[p^1][j][2];
     86 //        }
     87 //        p^=1;
     88 //    }
     89 //    printf("%d",f[p][0][2]);
     90 ////    f[p][0][2].print();
     91     int pre=0,suc=1,m=1024;
     92     for (int i=0;i<n;i++){
     93          suc=pre^1;
     94           for(int j=0;j<m;j++)
     95             for (int k=0;k<=2;k++)
     96                 f[suc][j][k]=f[pre][j][k];
     97         for (int j=0;j<m;j++)
     98         {
     99             int a=p[i+1]&j,x=p[i+1]^j;
    100             f[suc][a][1]+=f[pre][j][0]; f[suc][a][1]+=f[pre][j][1]; 
    101             f[suc][x][2]+=f[pre][j][1]; f[suc][x][2]+=f[pre][j][2];
    102         }
    103         pre=suc;
    104     }
    105     f[pre][0][2].print();    
    106     return 0;
    107 }

    Description

    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”。(不含引号)。
     

    Input

    第一行一个正整数Case,表示数据组数。
    每组数据第一行3个整数,分别为n, m, T。
    接下来m行,每行3个整数x, y, z,代表城市x和城市y之间有一条耗时为z的双向边。

    Output

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

    Sample Input

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

    Sample Output

    Possible
    Impossible
    【样例解释】
    第一组:0 -> 1 -> 2 :11
    第二组:显然偶数时间都是不可能的。
     

    Data Constraint

    30%:  T <= 10000 
    另有30%: n <= 5 , m <= 10.
    100%: 2 <= n <= 50 , 1 <= m <= 100 , 1 <= z <= 10000 , 1 <= T <= 10^18 , Case <= 5.

    如何将一个大数据问题缩小规模?

    在图论中,我们可以将它转化为最短路处理。

    考虑f[i][j]表示0~i点有一段路径为j。

    值代表什么先放一边,我们考虑在0->x->n-1的路径上有一个长度为d的环,我们一定可以绕它p次,即消耗p*d的时间,如果此时我们到n-1的路径长度为k,一定存在某一种情况使得k+p*d=T,这样就相当于在环上走了p圈。

    我们把问题规模缩小,从0出发到某个相邻的点,这段路径为d,如果我们绕着它走,相当于消耗了2*p*d的时间,假定有某种情况,路径长为k,一定可以看做在别的地方走了k%2d,剩下的路在d上来回走得到的。

    意思就是,将路径的所有距离全部模2d再处理问题。

    f[i][j]此时就是时间为j+2pd时最小的j+2pd。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 ll read(){
     5     ll x=0,f=1;
     6     char c=getchar();
     7     while(!isdigit(c)){
     8         if(c=='-') f=-1;
     9         c=getchar();
    10     }
    11     while(isdigit(c)){
    12         x=(x<<1)+(x<<3)+(c^48);
    13         c=getchar();
    14     }
    15     return x*f;
    16 }
    17 const ll inf=1e18;
    18 const int N=60;
    19 int n,m,p;
    20 ll T;
    21 ll f[55][20010];
    22 ll dis[N][20010];
    23 struct edge{
    24     int to,next,w;
    25 }e[N<<1];
    26 int head[N<<1],cnt;
    27 void addedge(int from,int to,int w){
    28     e[++cnt]=(edge){to,head[from],w};
    29     head[from]=cnt;
    30 }
    31 struct node{
    32     int pos,dis;
    33 };
    34 queue<node> q;
    35 int vis[N][20010];
    36 bool spfa(){
    37     for(int i=0;i<=n;i++){
    38         for(int j=0;j<=p;j++){
    39             dis[i][j]=inf;
    40             vis[i][j]=0;
    41         }
    42     }
    43     dis[1][0]=0;
    44     q.push((node){1,0});
    45     vis[1][0]=1;
    46     while(!q.empty()){
    47         node tmp=q.front();
    48         q.pop();
    49         vis[tmp.pos][tmp.dis]=0;
    50         ll u=tmp.pos,w1=tmp.dis;
    51         for(int i=head[u];i;i=e[i].next){
    52             ll v=e[i].to;
    53             ll w2=e[i].w;
    54             ll w=(w1+w2)%p;
    55             if(dis[u][w1]+w2<dis[v][w]){
    56                 dis[v][w]=dis[u][w1]+w2;
    57                 if(!vis[v][w]){
    58                     q.push((node){v,w});
    59                     vis[v][w]=1;
    60                 }
    61             }
    62         }
    63     }
    64     return dis[n][T%p]<=T;
    65 }
    66 int M;
    67 int main(){
    68     M=read();
    69     while(M--){
    70         n=read(),m=read(),T=read();
    71         p=200010;
    72         cnt=0;
    73         memset(head,0,sizeof(head));
    74         memset(e,0,sizeof(e));
    75         for(int i=1,x,y,z;i<=m;i++){
    76             x=read();y=read();z=read();
    77             x++,y++;
    78             addedge(x,y,z);
    79             addedge(y,x,z);
    80             if(x==1||y==1){
    81                 p=min(z*2,p);
    82             }
    83         }
    84         if(p==200010) printf("Impossible
    ");
    85         else if(spfa()){
    86             printf("Possible
    ");
    87         }
    88         else printf("Impossible
    ");
    89     }
    90     
    91     return 0;
    92 }
    ——抓住了时间,却不会利用的人,终究也逃不过失败的命运。
  • 相关阅读:
    Eclipse安装Hadoop插件
    (转)Ubuntu14.0.4中hadoop2.4.0伪分布模式配置
    Hadoop--DataNode无法启动
    启动与关闭hadoop
    hadoop中执行命令时发生错误
    strings命令
    Deriving data from ElasticSearch Engine
    elasticsearch data importing
    reading words in your computer and changing to female voice, linux festival text2wave saving wav files
    DDNS client on a Linux machine
  • 原文地址:https://www.cnblogs.com/Nelson992770019/p/11838570.html
Copyright © 2011-2022 走看看