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 }
    ——抓住了时间,却不会利用的人,终究也逃不过失败的命运。
  • 相关阅读:
    python pandas库和stats库计算偏度和峰度(附程序)
    python matplot 字体配置-中文手绘漫画风格
    流密码
    信息安全和密码学基础知识
    剑指offer48-把字符串转换成整数
    剑指offer47-不用加减乘除做加法
    剑指offer46-求1+2+...+n
    剑指offer45-孩子们的游戏
    剑指offer44-扑克牌顺子
    剑指offer43-翻转单词顺序列
  • 原文地址:https://www.cnblogs.com/Nelson992770019/p/11838570.html
Copyright © 2011-2022 走看看