CF实日录

C. Playlist

time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

You have a playlist consisting of nn songs. The ii-th song is characterized by two numbers titi and bibi — its length and beauty respectively. The pleasure of listening to set of songs is equal to the total length of the songs in the set multiplied by the minimum beauty among them. For example, the pleasure of listening to a set of 33 songs having lengths [5,7,4][5,7,4] and beauty values [11,14,6][11,14,6] is equal to (5+7+4)⋅6=96(5+7+4)⋅6=96.

You need to choose at most kk songs from your playlist, so the pleasure of listening to the set of these songs them is maximum possible.

Input

The first line contains two integers nn and kk (1≤k≤n≤3⋅1051≤k≤n≤3⋅105) – the number of songs in the playlist and the maximum number of songs you can choose, respectively.

Each of the next nn lines contains two integers titi and bibi (1≤ti,bi≤1061≤ti,bi≤106) — the length and beauty of ii-th song.

Output

Print one integer — the maximum pleasure you can get.

Examples

input

Copy

4 3
4 7
15 1
3 6
6 8

output

Copy

78

input

Copy

5 3
12 31
112 4
100 100
13 55
55 50

output

Copy

10000

Note

In the first test case we can choose songs 1,3,41,3,4, so the total pleasure is (4+3+6)⋅6=78(4+3+6)⋅6=78.

In the second test case we can choose song 33. The total pleasure will be equal to 100⋅100=10000100⋅100=10000.

#include<bits/stdc++.h>
using namespace std;
int n,k;
typedef long long ll;
pair<int,int> a[300010];
int main()
{
    cin>>n>>k;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i].second>>a[i].first;
    }
    sort(a+1,a+n+1);
    ll sum=0;
    ll res=0;
    set<pair<int,int> > s;
    for(int i=n;i>=1;i--){
        sum+=a[i].second;
        s.insert(make_pair(a[i].second,i));
        while((int)s.size()>k){
            auto it=s.begin();
            sum-=it->first;
            s.erase(it);
        }
        res=max(res,1ll*sum*a[i].first);
    }
    cout<<res<<endl;
    return 0;
}

D. Ehab and the Expected XOR Problem

time limit per test

1 second

memory limit per test

256 megabytes

input

standard input

output

standard output

Given two integers nn and xx, construct an array that satisfies the following conditions:

  • for any element aiai in the array, 1≤ai<2n1≤ai<2n;
  • there is no non-empty subsegment with bitwise XOR equal to 00 or xx,
  • its length ll should be maximized.

A sequence bb is a subsegment of a sequence aa if bb can be obtained from aa by deletion of several (possibly, zero or all) elements from the beginning and several (possibly, zero or all) elements from the end.

Input

The only line contains two integers nn and xx (1≤n≤181≤n≤18, 1≤x<2181≤x<218).

Output

The first line should contain the length of the array ll.

If ll is positive, the second line should contain ll space-separated integers a1a1, a2a2, ……, alal (1≤ai<2n1≤ai<2n) — the elements of the array aa.

If there are multiple solutions, print any of them.

Examples

input

Copy

3 5

output

Copy

3
6 1 3

input

Copy

2 4

output

Copy

3
1 3 1 

input

Copy

1 1

output

Copy

0

Note

In the first example, the bitwise XOR of the subsegments are {6,7,4,1,2,3}{6,7,4,1,2,3}.

链接

题意:给出n和x,求一个序列,使得序列的异或和不等于x或者0,并且序列的元素大小在2^{n}之内(不包括2^{n})。

思路:构造一个原序列a的前缀异或和数组b(ai^ai+1^...^aj==bj^bi-1),并且任意前缀和数组b里的任意i,j都不会得到x。

构造的方法是遍历1到(1<<n) 对每个数判断 i^x是否已经存在与数组之中,因为如果i^x已经存在再添加i 那么就会出现异或和等于x

(若a^x=b,则a^b=x)否则加入数组。最后对于所求序列a 每个ai 可由bi^bi-1得到。

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
int mark[1<<18];
vector <int> ans({0});
int main()
{
    int n,x;
    cin>>n>>x;
    mark[0]=1;
    for(int i=1;i<(1<<n);i++){
        if(mark[i^x]) continue;
        ans.push_back(i);
        mark[i]=1;
    }
    cout<<(ans.size()-1)<<endl;
    for(int i=1;i<(int)ans.size();i++){
        cout<<(ans[i]^ans[i-1])<<" ";
    }
    return 0;
}

D. 1-2-K Game

time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

Alice and Bob play a game. There is a paper strip which is divided into n + 1 cells numbered from left to right starting from 0. There is a chip placed in the n-th cell (the last one).

Players take turns, Alice is first. Each player during his or her turn has to move the chip 1, 2 or k cells to the left (so, if the chip is currently in the cell i, the player can move it into cell i - 1, i - 2 or i - k). The chip should not leave the borders of the paper strip: it is impossible, for example, to move it k cells to the left if the current cell has number i < k. The player who can't make a move loses the game.

Who wins if both participants play optimally?

Alice and Bob would like to play several games, so you should determine the winner in each game.

Input

The first line contains the single integer T (1 ≤ T ≤ 100) — the number of games. Next T lines contain one game per line. All games are independent.

Each of the next T lines contains two integers n and k (0 ≤ n ≤ 109, 3 ≤ k ≤ 109) — the length of the strip and the constant denoting the third move, respectively.

Output

For each game, print Alice if Alice wins this game and Bob otherwise.

Example

input

Copy

4
0 3
3 3
3 4
4 4

output

Copy

Bob
Alice
Bob
Alice

题意:两人玩游戏,轮流移动盘子,每次移动向左移动1步或者2步或者K步。盘子一开始在最左边下标为n的地方,一个玩家为赢的定义为最后一个人移动盘子到下标为0的地方(不能移到小于0的地方),Alice为先手。

题解:首先考虑没有K的时候,可以发现n可以分为任意组的1+2或者2+1,即如果n%3==0那么后手总有办法使得最后一个移动到0的人是后手,如果n%3!=0那么最后移动的人必为先手。现在考虑有K的时候,如果K%3==0,K的作用就是快速结束多个1+2的回合,必败态的位置为K+1,即若r=n%(K+1),r==K那么最后一次移动的人为先手,否则这一段就回到了没有K的情况,当r%3不为0的时候最后一个移动的为先手,否则为后手。

传送门之别人的题解:CF EDU 68 D

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

int main()
{
    int T;
    ll n,k;
    cin>>T;
    while(T--){
        cin>>n>>k;
        if(k%3!=0){
            if(n%3==0){
                cout<<"Bob"<<endl;
            }
            else{
                cout<<"Alice"<<endl;
            }
        }
        else {
            ll r=n%(k+1);
            if(r%3||r==k){
                cout<<"Alice"<<endl;
            }
            else cout<<"Bob"<<endl;
        }
    }
    return 0;
}

 

G. Privatization of Roads in Treeland

time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

Treeland consists of nn cities and n−1n−1 roads. Each road is bidirectional and connects two distinct cities. From any city you can get to any other city by roads. Yes, you are right — the country's topology is an undirected tree.

There are some private road companies in Treeland. The government decided to sell roads to the companies. Each road will belong to one company and a company can own multiple roads.

The government is afraid to look unfair. They think that people in a city can consider them unfair if there is one company which owns two or more roads entering the city. The government wants to make such privatization that the number of such cities doesn't exceed kk and the number of companies taking part in the privatization is minimal.

Choose the number of companies rr such that it is possible to assign each road to one company in such a way that the number of cities that have two or more roads of one company is at most kk. In other words, if for a city all the roads belong to the different companies then the city is good. Your task is to find the minimal rr that there is such assignment to companies from 11 to rr that the number of cities which are not good doesn't exceed kk.

The picture illustrates the first example (n=6,k=2n=6,k=2). The answer contains r=2r=2 companies. Numbers on the edges denote edge indices. Edge colors mean companies: red corresponds to the first company, blue corresponds to the second company. The gray vertex (number 33) is not good. The number of such vertices (just one) doesn't exceed k=2k=2. It is impossible to have at most k=2k=2 not good cities in case of one company.

Input

The first line contains two integers nn and kk (2≤n≤200000,0≤k≤n−12≤n≤200000,0≤k≤n−1) — the number of cities and the maximal number of cities which can have two or more roads belonging to one company.

The following n−1n−1 lines contain roads, one road per line. Each line contains a pair of integers xixi, yiyi (1≤xi,yi≤n1≤xi,yi≤n), where xixi, yiyi are cities connected with the ii-th road.

Output

In the first line print the required rr (1≤r≤n−11≤r≤n−1). In the second line print n−1n−1 numbers c1,c2,…,cn−1c1,c2,…,cn−1 (1≤ci≤r1≤ci≤r), where cici is the company to own the ii-th road. If there are multiple answers, print any of them.

Examples

input

Copy

6 2
1 4
4 3
3 5
3 6
5 2

output

Copy

2
1 2 1 1 2 

input

Copy

4 2
3 1
1 4
1 2

output

Copy

1
1 1 1 

input

Copy

10 2
10 3
1 2
1 3
1 4
2 5
2 6
2 7
3 8
3 9

output

Copy

3
1 1 2 3 2 3 1 3 1 

题意:给定一个无向连通图,每个点代表一个城市,每条边代表一条路,现在让一些公司去承包一些路,一个城市是否是好的定义是:连接这个城市的每一条边都是不同公司承包的。求最少的公司使得不好的城市不超过K个。

题解:最少的公司数量可以通过二分搜索找出,再根据这个数量输出方案(主要难在这里)通过DFS,每次遍历到一条边都输出上一次的下一个数,并且跳过一次和搜索进来时相同的数字。

#include <bits/stdc++.h>
using namespace std;
#define mod 1000000007
typedef long long ll;
#define inf 0x3f3f3f3f
int n,k;
const int maxn=200010;
vector<pair<int,int> > g[maxn];
int d[maxn];
int R;
int fan[maxn];
void dfs(int fa,int x,int c)
{
    int color=0;
    for(int i=0;i<g[x].size();i++){
        if(g[x][i].first!=fa){
            if(c==color){
                color=(color+1)%R;
                c=-1;
            }
            fan[g[x][i].second]=color;
            dfs(x,g[x][i].first,color);
            color=(color+1)%R;
        }
    }
}
bool check(int r)
{
    int ck=0;
    for(int i=1;i<=n;i++){
        if((int)g[i].size()>r) ck++;
        if(ck>k) return false;
    }
    return true;
}
int main()
{
    cin>>n>>k;
    int maxd=0,mind=inf;
    for(int i=1;i<n;i++){
        int x,y;
        cin>>x>>y;
        d[x]++;d[y]++;
        maxd=max(maxd,d[x]);maxd=max(maxd,d[y]);
        mind=min(mind,d[x]);mind=min(mind,d[y]);
        g[x].push_back(make_pair(y,i));
        g[y].push_back(make_pair(x,i));
    }
    int l=mind,r=maxd;
    while(l<r){
        int mid=(l+r)>>1;
        if(!check(mid)){
            l=mid+1;
        }
        else r=mid;
    }
    R=l;
    cout<<R<<endl;
    dfs(-1,1,-1);
    for(int i=1;i<=n-1;i++){
        cout<<fan[i]+1<<" ";
    }
    cout<<endl;
    return 0;
}

 

F2. Spanning Tree with One Fixed Degree

time limit per test

3 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

You are given an undirected unweighted connected graph consisting of nn vertices and mm edges. It is guaranteed that there are no self-loops or multiple edges in the given graph.

Your task is to find any spanning tree of this graph such that the degree of the first vertex (vertex with label 11 on it) is equal to DD (or say that there are no such spanning trees). Recall that the degree of a vertex is the number of edges incident to it.

Input

The first line contains three integers nn, mm and DD (2≤n≤2⋅1052≤n≤2⋅105, n−1≤m≤min(2⋅105,n(n−1)2),1≤D<nn−1≤m≤min(2⋅105,n(n−1)2),1≤D<n) — the number of vertices, the number of edges and required degree of the first vertex, respectively.

The following mm lines denote edges: edge ii is represented by a pair of integers vivi, uiui (1≤vi,ui≤n1≤vi,ui≤n, ui≠viui≠vi), which are the indices of vertices connected by the edge. There are no loops or multiple edges in the given graph, i. e. for each pair (vi,uivi,ui) there are no other pairs (vi,uivi,ui) or (ui,viui,vi) in the list of edges, and for each pair (vi,ui)(vi,ui) the condition vi≠uivi≠ui is satisfied.

Output

If there is no spanning tree satisfying the condition from the problem statement, print "NO" in the first line.

Otherwise print "YES" in the first line and then print n−1n−1 lines describing the edges of a spanning tree such that the degree of the first vertex (vertex with label 11 on it) is equal to DD. Make sure that the edges of the printed spanning tree form some subset of the input edges (order doesn't matter and edge (v,u)(v,u) is considered the same as the edge (u,v)(u,v)).

If there are multiple possible answers, print any of them.

Examples

input

Copy

4 5 1
1 2
1 3
1 4
2 3
3 4

output

Copy

YES
2 1
2 3
3 4

input

Copy

4 5 3
1 2
1 3
1 4
2 3
3 4

output

Copy

YES
1 2
1 3
4 1

input

Copy

4 4 3
1 2
1 4
2 3
3 4

output

Copy

NO

Note

The picture corresponding to the first and second examples:

The picture corresponding to the third example:

题意:给一个无向连通图,n个点,m条边,求一个生成树,要求一号点的度为D。

题解:显然如果一号点的度小于D的话,结果必然为NO。首先求出图中移除1号点的时候剩余的连通块,并且求出这些连通块的最小生成树,再将1号点连向各个连通块,如果连通块个数多于D,结果为NO。如果还不够D那么再随意连接别的点直至符合。最后通过求得的所有生成树的边,重新建图,在新的图上求最小生成树。本题容易错在,如果单单求与1号点连接的桥,每次都把桥边加上而已,也还会出现最后面无法将图连通的可能如 下面的数据2。

#include <bits/stdc++.h>
using namespace std;
#define mod 1000000007
typedef long long ll;
#define inf 0x3f3f3f3f
const int maxn=200010;
int n,m,D;
int d[maxn];
vector <int> g[maxn];
vector <pair<int,int> >ans;
int F[maxn];
int vis[maxn];
int low[maxn],dfn[maxn];
int father[maxn];
int ti=0;
int cnt=0;
int t=0;
void tarjan(int u,int fa)
{
    father[u]=fa;
    dfn[u]=low[u]=ti++;
    for(int i=0;i<g[u].size();i++){
        int k=g[u][i];
        if(dfn[k]==-1){
            tarjan(k,u);
            low[u]=min(low[u],low[k]);
        }
        else if(fa!=k){
            low[u]=min(low[u],dfn[k]);
        }
    }
}
void solve(int N)
{
    memset(dfn,-1,sizeof dfn);
    memset(low,-1,sizeof low);
    memset(father,0,sizeof father);
    for(int i=1;i<=N;i++){
        if(dfn[i]==-1){
            tarjan(i,i);
        }
    }
    for(int i=1;i<=N;i++){
        int v=father[i];
        if(v>0&&low[i]>dfn[v]){
            if(v==1||i==1){
                ans.push_back(make_pair(i,v));
                cnt++;
                if(v==1){
                    vis[i]=1;
                    F[i]=1;
                }
                if(i==1){
                    vis[v]=1;
                    F[v]=1;
                }
                t++;
                if(t>=D) break;
            }
        }
    }
}
int finds(int x)
{
    if(F[x]==-1) return x;
    else return F[x]=finds(F[x]);
}
map<int,int> mark;
int main()
{
    cin>>n>>m>>D;
    for(int i=1;i<=n;i++) F[i]=-1;
    for(int i=1;i<=m;i++){
        int u,v;
        cin>>u>>v;
        d[u]++;d[v]++;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    if(d[1]<D){
        cout<<"NO"<<endl;
    }
    else{
        for(int i=2;i<=n;i++){//以并查集的形式,将不包含1的点都求出他们的连通块
            for(int j=0;j<g[i].size();j++){
                int u=i;int v=g[i][j];
                int t1=finds(u);
                int t2=finds(v);
                if(t1!=t2){
                    if(u==1||v==1) continue ;
                    F[t1]=t2;
                    cnt++;
                    ans.push_back(make_pair(u,v));
                }
                if(ans.size()==n-1) break;
            }
            if(ans.size()==n-1) break;
        }
        solve(n);//将1号点的桥边加上
        for(int i=0;i<g[1].size();i++){//将1号点连接各个连通块
            if(t>=D) break;
            if(vis[g[1][i]]) continue ;
            if(mark[finds(g[1][i])]==1) continue;
            else mark[finds(g[1][i])]=1;
            F[g[1][i]]=1;
            ans.push_back(make_pair(1,g[1][i]));
            cnt++;
            t++;
            vis[g[1][i]]=1;
        }
        for(int i=0;i<g[1].size();i++){//如果度数还没够D,继续加边
            if(t>=D) break;
            if(vis[g[1][i]])continue;
            F[g[1][i]]=1;
            ans.push_back(make_pair(1,g[1][i]));
            t++;
        }
        for(int i=1;i<=n;i++){
            g[i].clear();
            F[i]=-1;
        }
        for(int i=0;i<ans.size();i++){//重新构图
            g[ans[i].first].push_back(ans[i].second);
            g[ans[i].second].push_back(ans[i].first);
        }
        ans.clear();
        for(int i=1;i<=n;i++){//再做一次Kruscal
            for(int j=0;j<g[i].size();j++){
                int t1=finds(i);
                int t2=finds(g[i][j]);
                if(t1!=t2){
                    F[t1]=t2;
                    ans.push_back(make_pair(i,g[i][j]));
                }
                if(ans.size()==n-1) break;
            }
            if(ans.size()==n-1) break;
        }
        if((int)ans.size()==n-1){
            cout<<"YES"<<endl;
            for(int i=0;i<ans.size();i++){
                cout<<ans[i].first<<" "<<ans[i].second<<endl;
            }
        }
        else{
            cout<<"NO"<<endl;
        }
    }
    return 0;
}
/*
7 7 3
1 7
1 3
3 5
1 5
1 2
2 4
2 6
*/

/*
7 8 4
1 2
1 3
1 4
1 5
1 6
1 7
7 6
5 4
*/

C. The Football Season

time limit per test

1 second

memory limit per test

256 megabytes

input

standard input

output

standard output

The football season has just ended in Berland. According to the rules of Berland football, each match is played between two teams. The result of each match is either a draw, or a victory of one of the playing teams. If a team wins the match, it gets ww points, and the opposing team gets 00 points. If the game results in a draw, both teams get dd points.

The manager of the Berland capital team wants to summarize the results of the season, but, unfortunately, all information about the results of each match is lost. The manager only knows that the team has played nn games and got pp points for them.

You have to determine three integers xx, yy and zz — the number of wins, draws and loses of the team. If there are multiple answers, print any of them. If there is no suitable triple (x,y,z)(x,y,z), report about it.

Input

The first line contains four integers nn, pp, ww and dd (1≤n≤1012,0≤p≤1017,1≤d<w≤105)(1≤n≤1012,0≤p≤1017,1≤d<w≤105) — the number of games, the number of points the team got, the number of points awarded for winning a match, and the number of points awarded for a draw, respectively. Note that w>dw>d, so the number of points awarded for winning is strictly greater than the number of points awarded for draw.

Output

If there is no answer, print −1−1.

Otherwise print three non-negative integers xx, yy and zz — the number of wins, draws and losses of the team. If there are multiple possible triples (x,y,z)(x,y,z), print any of them. The numbers should meet the following conditions:

  • x⋅w+y⋅d=px⋅w+y⋅d=p,
  • x+y+z=nx+y+z=n.

Examples

input

Copy

30 60 3 1

output

Copy

17 9 4

input

Copy

10 51 5 4

output

Copy

-1

input

Copy

20 0 15 5

output

Copy

0 0 20

Note

One of the possible answers in the first example — 1717 wins, 99 draws and 44 losses. Then the team got 17⋅3+9⋅1=6017⋅3+9⋅1=60 points in 17+9+4=3017+9+4=30 games.

In the second example the maximum possible score is 10⋅5=5010⋅5=50. Since p=51p=51, there is no answer.

In the third example the team got 00 points, so all 2020 games were lost.

题意:一场比赛赢了得W分,平局得d分,输了得0分。现在给出最后的得分p和比赛的总场数n,问赢了,平了,输了个多少局。

题解:假设赢了x场,平了y场,输了z场,则有x*w+y*d=p,那么如果y>w,可以有w*(x+a*d)+d*(y-a*w)=x*w+y*d,可以发现如果存在解,我们可以在0~w的范围内搜索到平局的答案。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

int main()
{
    ll n,p,w,d;
    cin>>n>>p>>w>>d;
    for(int i=0;i<=w;i++)
    {
        if((p-i*1ll*d)%w) continue;
        ll x=(p-i*1ll*d)/w;
        ll z=n-i-x;
        if(z<0||x<0) continue;
        cout<<x<<" "<<i<<" "<<z<<endl;
        return 0;
    }
    cout<<"-1"<<endl;
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值