codeforces hellow 2018 div.2

A. Modular Exponentiation
time limit per test1 second
memory limit per test256 megabytes
inputstandard input
outputstandard output
The following problem is well-known: given integers n and m, calculate

,
where 2n = 2·2·…·2 (n factors), and denotes the remainder of division of x by y.

You are asked to solve the “reverse” problem. Given integers n and m, calculate

.
Input
The first line contains a single integer n (1 ≤ n ≤ 108).

The second line contains a single integer m (1 ≤ m ≤ 108).

Output
Output a single integer — the value of .

Examples
input
4
42
output
10
input
1
58
output
0
input
98765432
23456789
output
23456789
Note
In the first example, the remainder of division of 42 by 24 = 16 is equal to 10.

In the second example, 58 is divisible by 21 = 2 without remainder, and the answer is 0.


题解。m%2^n,但是m是有范围的。很容易算出n大于多少时候m一定小于2^n。就可以分两类解决计算量小。也不会超范围了。

#include<bits/stdc++.h>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define PI 3.1415926 
using namespace std ;
typedef long long ll;
typedef unsigned long long ull;

const ll MAX = 100000000;
ll my_pow(int p){
    ll ret = 1;
    ll x = 2;
    while(p){
        if(p&1) ret = ret*x;
        x = x*x;
        p = p>>1;
    }
    return ret;
}
int main(){
    ll n,m;
    while(cin>>n>>m){
        if(n < 27){
            ll x = my_pow(n);
            cout<<m%x<<endl;;
        }
        else cout<<m<<endl;
    }
    return 0;
}

B. Christmas Spruce
time limit per test1 second
memory limit per test256 megabytes
inputstandard input
outputstandard output
Consider a rooted tree. A rooted tree has one special vertex called the root. All edges are directed from the root. Vertex u is called a child of vertex v and vertex v is called a parent of vertex u if there exists a directed edge from v to u. A vertex is called a leaf if it doesn’t have children and has a parent.

Let’s call a rooted tree a spruce if its every non-leaf vertex has at least 3 leaf children. You are given a rooted tree, check whether it’s a spruce.

The definition of a rooted tree can be found here.

Input
The first line contains one integer n — the number of vertices in the tree (3 ≤ n ≤ 1 000). Each of the next n - 1 lines contains one integer pi (1 ≤ i ≤ n - 1) — the index of the parent of the i + 1-th vertex (1 ≤ pi ≤ i).

Vertex 1 is the root. It’s guaranteed that the root has at least 2 children.

Output
Print “Yes” if the tree is a spruce and “No” otherwise.

Examples
input
4
1
1
1
output
Yes
input
7
1
1
1
2
2
2
output
No
input
8
1
1
1
1
3
3
3
output
Yes
Note
The first example:


最开始理解错了意思。是所有有孩子的节点满足。不是根。用vector建树,然后递归就可以了。

#include<bits/stdc++.h>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define PI 3.1415926 
using namespace std ;
typedef long long ll;
typedef unsigned long long ull;

vector<int> m[1000+50];
bool k ;
void find(int rt){
    int c = m[rt].size();
    if(c < 3){
        k = false;
        return ;
    }
    for(int i = 0 ; i < m[rt].size() ; i++){
        int son = m[rt][i];
        if(m[son].size()){
            c--;
            find(son);
        }

    }
    if(c < 3)   k = false;  
    return ;
}
int main(){
    int n ;
    while(cin>>n){
        k = true;
        int a;
        for(int i = 2 ; i <= n ; i++){
            cin>>a;
            m[a].push_back(i);
        }
        find(1);
        if(k) cout<<"Yes"<<endl;
        else cout<<"No"<<endl;
        for(int i = 1 ; i <= n ; i++)
            m[i].clear();
    }
    return 0;
}

C. Party Lemonade
time limit per test1 second
memory limit per test256 megabytes
inputstandard input
outputstandard output
A New Year party is not a New Year party without lemonade! As usual, you are expecting a lot of guests, and buying lemonade has already become a pleasant necessity.

Your favorite store sells lemonade in bottles of n different volumes at different costs. A single bottle of type i has volume 2i - 1 liters and costs ci roubles. The number of bottles of each type in the store can be considered infinite.

You want to buy at least L liters of lemonade. How many roubles do you have to spend?

Input
The first line contains two integers n and L (1 ≤ n ≤ 30; 1 ≤ L ≤ 109) — the number of types of bottles in the store and the required amount of lemonade in liters, respectively.

The second line contains n integers c1, c2, …, cn (1 ≤ ci ≤ 109) — the costs of bottles of different types.

Output
Output a single integer — the smallest number of roubles you have to pay in order to buy at least L liters of lemonade.

Examples
input
4 12
20 30 70 90
output
150
input
4 3
10000 1000 100 10
output
10
input
4 3
10 100 1000 10000
output
30
input
5 787787787
123456789 234567890 345678901 456789012 987654321
output
44981600785557577


这道题做了很久。首先,我将它定义成一道背包问题。但是DP所需的空间太多,所以自然不是背包问题可以解决的。然后,我试图用贪心的办法解决,但是被自己推翻了。然后用dfs,但是无论怎么怎么需处理和剪枝,要么是wa要么是超时。最后还是要怪自己对二进制不够敏感,都是2的幂,所以也就可以用二进制的思路来解决。至于预处理,当然也就不需要我最开始的p/v来进行排序了。因为一些数据是可以替换的。约束条件应该为(i>1) p[i]=min(p[i],2*p[i-1])以及p[i-1]=min(p[i],p[i-1])。但是一定注意,是从小到大的时候进行约束,至于为什么,因为大的体积不能拆开啊- -。预处理完,就可以确保在i和i-1中为最优,然后从n开始向后递推乘2。然后根据二进制来进行计算就行了。但是注意的是,因为处理的原因,可能p[i+1]会大于ans,比如例2中。所以需要ans=min(ans,p[i+1]);为什么是i+1?因为i+1一定大于前面所有的啊。

#include<bits/stdc++.h>
#define PI 3.1415926 
#define INF 1e18 
using namespace std ;
typedef long long ll;
typedef unsigned long long ull;

const ll _max = 32;

ll my_pow(int p){
    ll x = 2;
    ll ret = 1;
    while(p){
        if(p&1) ret*=x;
        x*=x;
        p>>=1;
    }
    return ret;
}
ll v[_max],p[_max];
int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(0),cout.tie(0); 
    int n,l;
    for(int i = 1 ; i <= _max ; i++){
        v[i] = my_pow(i-1);
    }
    while(cin>>n>>l){
        for(int i = 1 ; i <= n ; i++){
            cin >> p[i];
            if(i-1) p[i] = min(p[i],2*p[i-1]);
            if(i-1) p[i-1] = min(p[i],p[i-1]);
        }
        for(int i = n+1 ; i <= _max ; i++)
            p[i] = 2*p[i-1];
        ll ans = 0;
        for(int i = 1 ; i <= _max-2 ; i++){
            if(l & (1<<(i-1))) ans += p[i];
            ans = min(ans,p[i+1]);          
        }
        cout<<ans<<endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值