2016年8月8日 星期一

(UVA) 775 - Hamiltonian Cycle [Hamiltonian Cycle]

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=24&page=show_problem&problem=716

Hamitioniam Cycle,就是經過每個點,最後形成環!

http://www.csie.ntnu.edu.tw/~u91029/Circuit.html#1

可以參考這個喔!

反正我是記得:圓環變成路徑,路徑變成圓環!如果沒有的話,就往外擴張。

理論上是O (V^2)了,可是我不小心code成 O(V^2 lg V) set 的部分!


#include <iostream>
#include <stdio.h>
#include <cstring>
#include <set>
using namespace std;

const int MAX_N = 261;
int w[MAX_N][MAX_N];
int f[MAX_N],b[MAX_N]; //front, back

int main (){
//    ios::sync_with_stdio(0);
//    cin.tie(0);
    int n;
    while (cin >> n) {
//        cout<<"in\n";
        getchar();
        string ss;
        memset(w,0,sizeof(w));
        while (1) {
            getline(cin,ss);
            if (ss=="%") break;
//            cout<<"s="<<s<<".\n";
            int i=0,j=0;
            int len=ss.size();
            bool check=false;
            for (int x=0;len>x;x++) {
                if (check && '0'<=ss[x] && ss[x]<='9') {
                    j*=10;
                    j += (ss[x]-'0');
                }
                else if (!check && '0'<=ss[x] && ss[x]<='9') {
                    i*=10;
                    i += (ss[x]-'0');
                }
                else if (ss[x] == ' ') check=true;
            }
//            cout<<"i="<<i<<" , j="<<j<<" test\n";
            w[i][j] = 1;
            w[j][i] = 1;
        }
        memset(b,0,sizeof(b));
        memset(f,0,sizeof(f));
        int p1=1,pn=1;
        int cnt=1;
        int edg=0;
        bool cycle=false;
        bool ans=false;
        set<int> s;
        s.insert(1);
        while (1) {
//            if (cnt==1) goto aaa;
//            cout<< " queue : ";
//            printf("%d ",p1);
//            for (int x=f[p1];;x=f[x]) {
//                if (x==0) break;
//                if (x==p1) {
//                    printf("%d\n",x);
//                    break;
//                }
//                else printf("%d ",x);
//            }
//            aaa:
//            cout<<"p1="<<p1<<" , pn="<<pn<<" , cnt="<<cnt<<endl;
//            cout<<"cnt = "<<cnt<<endl;
            if (cycle) {
                if (cnt == n) {
                    ans=true;
                    break;
                }
                //get a something else
                bool GET=false;
                for (int i=1;n>=i;i++) {
                    if (s.find(i) == s.end()) {  //not in cycle
                        for (int j=1;n>=j;j++) {
                            if (i!=j && w[i][j]==1 && s.find(j) != s.end()) {
                                int tmp=f[j];
                                f[j] = i;
                                b[i] = j;
                                b[tmp]=0;
                                s.insert(i);
                                p1=tmp;
                                pn=i;
                                cnt++;
                                GET=true;
                                break;
                            }
                        }
                    }
                    if (GET) break;
                }
                cycle=false;
            }
//            cout<<"in\n";
            //become cycle
            bool move = false;
            for (int x=p1;x != pn; x=f[x]) {
                int nxt=f[x];
                if (w[nxt][p1] == 1 && w[x][pn] == 1) {
                    move=true;
                    f[x] = pn;
                    for (int i=pn;i!=nxt;i=f[i]) {
                        f[i] = b[i];
                        b[i] = x;
                        x=i;
                    }
                    f[nxt]=p1;
                    b[p1]=nxt;
                    b[nxt]=x;
                    break;
                }
            }
//            cout<<"in\n";
            cycle=move;
            if (!move) {
                for (int i=1;n>=i;i++) {
                    if (pn != i && s.find(i) == s.end() && w[i][pn] == 1) {
                        f[pn] = i;
                        b[i] = pn;
                        pn=i;
                        s.insert(i);
                        cnt++;
                        cycle=false;
                        break;
                    }
                }
                for (int i=1;n>=i;i++) {
                    if (p1 != i && s.find(i) == s.end() && w[i][p1] == 1) {
                        f[i] = p1;
                        b[p1] = i;
                        p1=i;
                        s.insert(i);
                        cnt++;
                        cycle=false;
                        break;
                    }
                }
            }
//            system("pause");
        }
        if (cnt==n) {
            printf("%d ",p1);
            for (int x=f[p1];;x=f[x]) {
                if (x==p1) {
                    printf("%d\n",x);
                    break;
                }
                else printf("%d ",x);
            }
        }
        else puts("N");
        
    }
}

Codeforces Round #366 (Div. 2)

http://codeforces.com/contest/705

最近好久沒po CF詳解了,因為最近都在刷UVA。之後有空會慢慢補上之前的,並且會盡力AC全部的題目。 ^_^

題目:
pA : http://codeforces.com/contest/705/problem/A
pB : http://codeforces.com/contest/705/problem/B
pC : http://codeforces.com/contest/705/problem/C
pD : http://codeforces.com/contest/705/problem/D
pE : http://codeforces.com/contest/705/problem/E

我AC的code:
pA : http://codeforces.com/contest/705/submission/19688112
pB : http://codeforces.com/contest/705/submission/19698156
pC : http://codeforces.com/contest/705/submission/19697521
pD : http://codeforces.com/contest/705/submission/19726277

題解:

pA :
題目大意:n=1 : I hate it. n=2 : I hate that I loveit. n=3 : I hate that I lovethat I hate it. n=4 : I hate that I lovethat I hate that I loveit. 以此類推

solution :
當n%2==1時,輸出I hate ,n%2==0時,輸出I love 。之後再處理一下that 跟 it。
可以看code理解一下喔。

pB :
簡化版題目大意:給你n個數字(1<=n<=10^5),對於某個大於1的數字,你可以選擇把那個數字分解成p , x-p (1<=p < 某個數字),誰先不能做出動作,誰就輸了。

solution :
可以想像的事說,我們可以想像:美個數字 - 1 之後,代表這個數字還可以被分解的次數!因此,我們可以維護 (每個數字-1) 的和,用%2去判斷輸贏!

注意一點,如果sum沒有 long long 維護,也是okay了(overflow時奇偶性是對的)!

pC :
題目大意:你有q個手機app,每個手機app一次都會發出一個通知(notification)。現在你要支援3件事情:1. 某個應用程式x 發出一個通知 2.你讀了應用程式x的所有通知 3. 你讀了前t個通知 。每筆操作過後,都要輸出目前有多少通知是沒有被讀到的(unread)。

solution :
我這題是用deque做,複雜度是 均攤O(N) 。
對於每個deque[i],你就維護第i個應用程式中,未讀的編號!然後你還要順便紀錄第三筆測資的t做到哪裡。還要順便紀錄第x個通知有沒有被使用過、以及第i個通知是由哪個app發送的。

那,對於操作1,你就deq[x] . push_back(cur_id),順便其他的紀錄一下。對於操作2,你就把deq 給 clear掉就好,順便紀錄哪個被用過。對於操作3,你就均攤O(N)掃過即可。詳細的話,認真看我的code吧 XD。

pD :
題目大意:你要完成一個給定起點、終點的Hamilton Path,每個Path都有不同的weight。你要使得weight的和最小。圖是一張完全圖。

solution :
看code吧~。

主要就是說:每次當你要多一個點時,你就很greedy的找一個最好的,之後破壞掉(重建)!








2016年8月5日 星期五

(UVA) 12442 - Forwarding Emails

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=24&problem=3873

DFS就對了,不要想這麼多XD!


#include <iostream>
#include <stdio.h>
#include <vector>
#include <cstring>
using namespace std;

const int MAX_N = 50002;
bool visit[MAX_N];
int rudu[MAX_N];
int ans[MAX_N];
int root[MAX_N];
vector<int> edg[MAX_N];

void init(int n) {
    memset(rudu,0,sizeof(rudu));
    for (int x=0;n>=x;x++) {
        edg[x].clear();
        visit[x]=false;
        ans[x]=0;
        root[x]=x;
    }
}

int DFS(int id) {
    visit[id]=true;
    int total=0;
    for (auto i = edg[id].begin();i!=edg[id].end();i++) {
        int tmp=*i;
        if (visit[tmp]==false) {
            total = max(total,DFS(tmp)+1);
        }
    }
    visit[id]=false;
    return ans[id]=total;
}

int main () {
//    freopen("input.txt","r",stdin);
//    freopen("output.txt","w",stdout);
    int T;
    scanf("%d",&T);
    for (int qq=0;T>qq;qq++) {
        int n;
        scanf("%d",&n);
        init(n);
        for (int x=0;n>x;x++) {
            int i,j;
            scanf("%d %d",&i,&j);
            rudu[j]++;
            edg[i].push_back(j);
        }
        //don't be so complicated, just DFS !!!
        int mn=-1;
        int id=-1;
        for (int x=1;n>=x;x++) {
            if (ans[x]==0) DFS(x);
            if (ans[x]>mn) {
                mn=ans[x];
                id=x;
            }
        }
        printf("Case %d: ",qq+1);
        printf("%d\n",id);
    }
}


2016年8月4日 星期四

(UVA) 10462 - Is There A Second Way Left? [次小MST --- Kruskal + LCA]

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=24&problem=1403

這題也是次小生成樹,跟 UVA 10600 一樣。

不過這份code,我是用Kruskal求MST,不同於Prim的是,Kruskal還要再DFS一次求整棵樹的樣子,Prim不用(詳細可以看code)


#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <utility>
#include <cstring>
#include <cstdlib>
#include <vector>
using namespace std;

typedef long long LL;
typedef pair<int,int> pii;
const int MAX_N = 105;
const int MAX_M = 205;
const int MAX_P = 10; //lgN
const int INF = 1e9+7;

struct Edge {
    int a,b,c;
} edg[MAX_M];

bool operator<(const Edge &e1,const Edge &e2) {
    return e1.c<e2.c;
}

Edge MP(int _a,int _b,int _c) {
    Edge ret;
    ret.a=_a;
    ret.b=_b;
    ret.c=_c;
    return ret;
}

struct DisjointSet {
    int p[MAX_N];
    void init(int n) {
        for (int x=0;n>=x;x++) p[x]=x;
    }
    int Find(int x) {
        return p[x]==x?x:p[x]=Find(p[x]);
    }
    void Union(int x,int y) {
        p[Find(x)] = Find(y);
    }
} djs;

int parent[MAX_N];
int depth[MAX_N];
pii lca[MAX_P][MAX_N];
vector<pii> tree_edg[MAX_N];  //end, weight
bool visit[MAX_N];
bool in_MST[MAX_M];
int binary[MAX_P];

void init() {
    for (int x=0;MAX_N>x;x++) tree_edg[x].clear();
}

int Kruskal(int n,int m) {
    for (int x=0;m>x;x++) in_MST[x]=false;
    djs.init(n);
    sort(edg,edg+m);
    int cnt=0;
    int ret=0;
    for (int i=0;m>i;i++) {
        while (i<m && djs.Find(edg[i].a) == djs.Find(edg[i].b)) i++;
        if (i==m) break;
        ret += edg[i].c;
        int a=edg[i].a;
        int b=edg[i].b;
        int c=edg[i].c;
        tree_edg[a].push_back(make_pair(b,c));
        tree_edg[b].push_back(make_pair(a,c));
        in_MST[i]=true;
        cnt++;
        djs.Union(edg[i].a,edg[i].b);
    }
    return (cnt==n-1?ret:-1);
}

void build_tree(int id,int cur_depth) {
    visit[id]=true;
    depth[id] = cur_depth;
    for (vector<pii>::iterator i=tree_edg[id].begin();i!=tree_edg[id].end();i++) {
        pii a=*i;
        int t=a.first;
        if (visit[t]==false) {
            build_tree(t,cur_depth+1);
            parent[t]=id;
            lca[1][t] = make_pair(id,a.second);
        }
    }
}

pii walk(int x,int depth) {
//    cout<<"x="<<x<<" , depth="<<depth<<" , ";
    memset(binary,0,sizeof(binary));
    int tmp=depth;
    int id=1;
    while (tmp>0) {
        binary[id++] = tmp%2;
        tmp/=2;
    }
    int mx=0;
    for (int i=1;id>i;i++) {
        if (binary[i]==1) {
            mx=max(mx,lca[i][x].second);
            x = lca[i][x].first;
        }
    }
//    cout<<x<<","<<mx<<endl;
    return make_pair(x,mx);
}

int FFind(int x,int y) {
    int L=1,R=min(depth[x],depth[y]) + 1;
    while (R-L!=1) {
        int mid=(L+R)>>1;
//        cout<<"mid="<<mid<<endl;
        if (walk(x,depth[x]-mid).first == walk(y,depth[y]-mid).first) L=mid;
        else R=mid;
    }
    return max(walk(x,depth[x]-L).second,walk(y,depth[y]-L).second);
}

int main (){
    int T;
    scanf("%d",&T);
    for (int qq=0;T>qq;qq++) {
        int n,m;
        scanf("%d %d",&n,&m);
        for (int x=0;m>x;x++) {
            int i,j,k;
            scanf("%d %d %d",&i,&j,&k);
            edg[x]=MP(i,j,k);
        }
        if (n>m+1) {
            printf("Case #%d : No way\n",qq+1);
            continue;
        }
        init();
        int sum=Kruskal(n,m);
        if (sum==-1) {
            printf("Case #%d : No way\n",qq+1);
            continue;
        }
        if (n==m+1) {
            printf("Case #%d : No second way\n",qq+1);
            continue;
        }
        //seen 1 as root
        for (int x=0;n>=x;x++) lca[0][x] = make_pair(x,0);
        for (int x=0;MAX_P>x;x++) lca[x][1] = make_pair(1,0);
        for (int x=1;n>=x;x++) visit[x]=false;
        parent[1]=1;
        build_tree(1,1);
        for (int x=2;MAX_P>x;x++) {
            for (int y=2;n>=y;y++) {
                lca[x][y] = make_pair(lca[x-1][lca[x-1][y].first].first , max(lca[x-1][y].second,lca[x-1][lca[x-1][y].first].second));
            }
        }
//        for (int x=0;MAX_P>x;x++) {
//            for (int y=0;n>=y;y++) {
//                cout<<lca[x][y].first<<','<<lca[x][y].second<<' ';
//            }
//            cout<<endl;
//        }
        int ans=INF;
        for (int x=0;m>x;x++) {
            if (in_MST[x]==false) {
                int ret=FFind(edg[x].a,edg[x].b);
                ans = min(ans,sum -ret + edg[x].c);
            }
        }
        printf("Case #%d : %d\n",qq+1,ans);
    }
}


(UVA) 1216 - The Bug Sensor Problem

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=24&problem=3657

其實這題跟 UVA 10369 一樣 XD



#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <utility>
#include <cmath>
#include <queue>
using namespace std;

typedef pair<double,double> pdd;
const int MAX_N = 1e5+6;
const double INF = 1e9+7;

inline double dis(pdd a,pdd b) {
 return sqrt((a.first-b.first)*(a.first-b.first) + (a.second-b.second)*(a.second-b.second));
}

double d[MAX_N];
pdd v[MAX_N];
bool visit[MAX_N];
int parent[MAX_N];  //to collect edge, we need that!

double Prim(int n,int m) {
priority_queue<double> que;

double mx=0.0;

 for (int x=0;n>x;x++) {
  d[x] = 1e9+7;
  visit[x]=false;
 }

 d[0]=0.0;
 parent[0]=0;

 for (int x=0;n>x;x++) {
  double min=INF;
  int p;
  for (int y=0;n>y;y++) {
   if (visit[y]==false && d[y]<min) {
    p=y;
    min=d[y];
   }
  }
  //we select p
  visit[p]=true;
  que.push(dis(v[p],v[parent[p]]));
//  cout<<"get "<<p<<" & "<<parent[p]<<endl;
  for (int y=0;n>y;y++) {
   if (visit[y]==false && dis(v[p],v[y]) < d[y]) {
    d[y] = dis(v[p],v[y]);
    parent[y]=p;
   }
  }
 }
 for (int x=0;m-1>x;x++) que.pop();
 return que.top();
}

int main () {
// freopen("output.txt","w",stdout);
 int T;
 scanf("%d",&T);
 for (int qq=0;T>qq;qq++) {
  int m,n=0;
  scanf("%d",&m);
  int x=0;
  while(1) {
 
   int i,j;
   scanf("%d",&i);
   if (i!=-1) scanf("%d",&j);
   else break;
   v[x]=make_pair(i,j);
   n++;
   x++;
  }
  double ret=Prim(n,m);
  if (ret - int(ret) > 1e-9) printf("%d\n",int(ret) + 1);
  else printf("%.0f\n",ret);
 }
// puts("");
}

(UVA) 11747 - Heavy Cycle Edges

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=24&problem=2847

題目大意:一個圖G(V,E),找出所有環中的最大值。

那就把MST求出後,輸出所有剩下邊即可。


#include <iostream>
#include <stdio.h>
#include <algorithm>
using namespace std;

typedef long long LL;
const int MAX_N = 1004;
const int MAX_M = 25006;

struct Edge {
 int a,b;
 LL c;
} edg[MAX_M];

bool operator<(const Edge &e1,const Edge &e2){
 return e1.c<e2.c;
} 

Edge MP(int _a,int _b,LL _c) {
 Edge ret;
 ret.a=_a;
 ret.b=_b;
 ret.c=_c;
 return ret;
}

struct DisjointSet {
 int p[MAX_N];
 void init(int n) {
  for (int x=0;n>=x;x++) p[x]=x;
 }
 int Find(int x) {
  return p[x]==x?x:p[x]=Find(p[x]);
 }
 void Union(int x,int y) {
  p[Find(x)]=Find(y);
 }
} djs;

bool Kruskal(int n,int m) {
 sort(edg,edg+m);
 djs.init(n);
 bool ret=false;
 for (int i=0;m>i;i++) {
  while (i<m && djs.Find(edg[i].a) == djs.Find(edg[i].b)) {
   if (ret) printf(" %lld",edg[i].c);
   else if (!ret) printf("%lld",edg[i].c);
   i++;
   ret=true;
  }
  djs.Union(edg[i].a,edg[i].b);
 }
 return ret;
}

int main () {
 int n,m;
 while (scanf("%d %d",&n,&m) != EOF) {
  if (n==0 && m==0) break;
  for (int x=0;m>x;x++) {
   int i,j,k;
   scanf("%d %d %d",&i,&j,&k);
   edg[x] = MP(i,j,k);
  }
  if (!Kruskal(n,m)) printf("forest");
  puts("");
 }
}


(UVA) 10600 - ACM Contest and Blackout [次小生成樹---Prim,LCA]

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=24&problem=1541

這題簡單來講,是求 "次小生成樹" 。

那,就是先把MST找出來,之後每找一個邊 (注意有重邊!!!),試著帶帶看。

那,求的過程中,我們需要LCA(lowest common ancestor)幫助!

用Kruskal求次小MST

我是用Prim求MST

#include <iostream>
#include <stdio.h>
#include <cstring>
#include <utility>
#include <cmath>
using namespace std;

typedef pair<int,int> pii;
const int MAX_N = 103;
const int MAX_P = 11;  //MAX_P = log(MAX_N)
const int INF = 1e9+7;

bool visit[MAX_N];
int d[MAX_N];
int parent[MAX_N];
int w1[MAX_N][MAX_N];
int w2[MAX_N][MAX_N];
int depth[MAX_N];
int binary[MAX_P];
pii lca[MAX_P][MAX_N];

void init() {
 for (int x=0;MAX_N>x;x++) {
  for (int y=0;MAX_N>y;y++) {
   w1[x][y] = w2[x][y] = INF;
  }
 }
}

int Prim(int n) {
 int sum=0;
 
 for (int x=1;n>=x;x++) {
  d[x]=INF;
  visit[x]=false;
 }
 
 parent[1]=1;
 d[1]=0;
 depth[1]=0;
 
 for (int x=0;n>x;x++) {
//  cout<<"x="<<x<<" , sum="<<sum<<endl;
  int p,min=INF;
  for (int y=1;n>=y;y++) {
   if (!visit[y] && d[y] < min) {
    min=d[y];
    p=y;
   }
  }
  if (p!=parent[p])sum += w1[p][parent[p]];
  visit[p]=true;
  depth[p] = depth[parent[p]] + 1;
  
  for (int y=1;n>=y;y++) {
   if (!visit[y] && d[y] > w1[p][y]) {
    d[y]=w1[p][y];
    parent[y]=p;
   }
  }
 }
 return sum;
}

void LCA(int n) {
 for (int x=0;MAX_P>x;x++) {
  for (int y=1;n>=y;y++) {
   if (y==1) lca[x][y] = make_pair(y,0);
   else if (x==0)lca[x][y] = make_pair(y,0);
   else if (x==1) lca[x][y] = make_pair(parent[y],w1[y][parent[y]]);
   else lca[x][y] = make_pair(lca[x-1][lca[x-1][y].first].first,max(lca[x-1][y].second,lca[x-1][lca[x-1][y].first].second));
  }
 }
}

pii walk(int x,int depth) {
// cout<<"walk : "<<x<<" , "<<depth;
 memset(binary,0,sizeof(binary));
 int id=1;
 int tmp=depth;
 while (tmp>0) {
  binary[id++] = tmp%2;
  tmp/=2;
 }
 int mx=0;
 for (int i=1;id>i;i++) {
  if (binary[i]==1) {
   mx = max(mx,lca[i][x].second);
   x = lca[i][x].first;
  }
 }
// cout << "  :  "<<x<<" , "<<mx<<endl;
 return make_pair(x,mx);
}

int Find(int x,int y) {
 int L=1,R=min(depth[x],depth[y])+1;
 while (R-L!=1) {
//  cout<<L<<" ~ "<<R<<endl;
  int mid=(L+R)>>1;
  if (walk(x,depth[x]-mid).first == walk(y,depth[y]-mid).first) L=mid;
  else R=mid;
 }
// cout<<"L="<<L<<endl;
 return max(walk(x,depth[x]-L).second,walk(y,depth[y]-L).second);
}

int main () {
// freopen("output.txt","w",stdout);
 int T;
 scanf("%d",&T);
 while (T--) {
  init();
  int n,m;
  scanf("%d %d",&n,&m);
  for (int x=0;m>x;x++) {
   int a,b,c;
   scanf("%d %d %d",&a,&b,&c);
   if (w1[a][b] == INF) {
    w1[a][b] = c;
    w1[b][a] = c;
   }
   else {
    int tmp=w1[a][b];
    w1[a][b] = min(w1[a][b],c);
    tmp=max(tmp,c);
    w2[a][b] = min(w2[a][b],tmp);
    w1[b][a] = w1[a][b];
    w2[b][a] = w2[a][b];
//    cout<<"GETTTT   "<<w1[a][b] << ' '<<w2[a][b]<<endl;
   }
  }
  int sum=Prim(n);
//  for (int x=1;n>=x;x++) cout<<parent[x] << ' ';
//  cout<<endl;
//  for (int x=1;n>=x;x++) cout<<depth[x]<<' ';
//  cout<<endl;
  LCA(n);
//  for (int x=0;4>x;x++) {
//   for (int y=1;n>=y;y++) {
//    cout<<lca[x][y].first<< ","<<lca[x][y].second<<" ";
//   }
//   cout<<endl;
//  }
  int ans2=INF;
//  cout<<Find(5,3)<<endl;
  for (int i=1;n>=i;i++) {
   for (int j=1;n>=j;j++) {
    if (i==j) continue;
    if (parent[i]==j || parent[j]==i) {  //重邊 
//     cout<<"i = "<<i<<" , j="<<j<<", new="<<sum+w2[i][j] - w1[i][j]<<endl;
     if (w2[i][j] != INF) {
      ans2 = min(ans2,sum+w2[i][j] - w1[i][j]);
     }
    }
    else if (w1[i][j] != INF) {
     int ret=Find(i,j);
//     cout<<"i="<<i<<" , j="<<j<<" ret = "<<ret<<" , new = "<<sum+w1[i][j] - ret<<endl;
     ans2 = min(ans2,sum+w1[i][j] - ret);
    }
   }
  }
  printf("%d %d\n",sum,ans2);
 }
}