Codeforces Round #384 (Div. 2) B ,C ,D(规律,数学。树dp)

本文解析了多个算法题目,包括寻找序列中特定位置的数值、解决分数等式的整数解以及最大子树和的问题。提供了高效算法实现,并通过代码示例展示了如何优化算法以达到更好的性能。
题目大意:

构造一个1213121412131215121312141213121…
输入n,k,求k位置的数。 

然后现在问你k位置是什么

B题

  第i个数是多少,就是i的质因数分解中2的幂次是多少。当然也可以递归做
  推了一下发现和n无关一个长度很长的序列构造肯定不行,每次对除以二直到第一次不能整除。


int main(){
    LL len=0;
    LL n,k;cin>>n>>k;

    rep(i,1,n)len=len*2+1;
    LL kk=k;
    for(int i=n;i>=1;--i){
        len=len/2;
        if(kk==len+1){
            pf("%d\n",i);return 0;
        }
        if(kk>len)kk-=len+1;
    }
}

大神的理解:实际上就是这个数字k的二进制最小的1的位数的位置。

    #include<bits/stdc++.h>  
    using namespace std;  
    long long n,p;  
    int main()  
    {  
        scanf("%lld%lld",&n,&p);  
        cout<<log2(p&(-p))+1<<endl;  
    }  

参考http://blog.youkuaiyun.com/qq_31917799/article/details/53957864

大概意思就是给一个整数n,找到三个不同的整数x,y,z,使得
2/n = 1/x + 1/y + 1/z
成立。
分析下,一般容易想到令其中一个数为n,因为 
2/n = 1/n + 1/n,
这样我们只要找到x,y满足 
1/n = 1/x + 1/y。
我们只要找到合理的x,y即可。
由 1/n = 1/x + 1/y 
可得到     y = n*x/(x - n),
要使得y为整数,令分母为1就可以了,
所以,x = n + 1,
这个时候 y = n * ( n + 1 ),
当n为1时, x = y,要输出-1。
    #include <iostream>  
    using namespace std;  

    int main ()  
    {  
        int n;  
        cin >> n;  
        if (n > 1)  
            cout << n << " " << n + 1 <<" "<< (n + 1)*n << endl;  
        else cout << "-1" << endl;  
        return 0;  
    }  

D. Chloe and pleasant prizes

题目大意:

已知一颗以1为根的树,让你找两个不相交的子树,使其和最大,如果找不到满足条件的解,输出Impossible
int n;
int a[N];
LL ans;
LL dp[N];
int fst[N],nxt[N<<1],vv[N<<1],e;
void add(int u,int v){
    vv[e]=v;nxt[e]=fst[u];fst[u]=e++;
}
LL sum[N];
void dfs(int u,int p){
    LL tmp=0;
    for(int i=fst[u];~i;i=nxt[i]){
        int v=vv[i];
        if(v==p)continue;
        dfs(v,u);
        tmp+=sum[v];
        ans=max(ans,dp[u]+dp[v]);
        dp[u]=max(dp[u],dp[v]);
    }
    sum[u]+=tmp;
    sum[u]+=a[u];
    dp[u]=max(dp[u],sum[u]);
    //dp[u]=max(dp[u]+a[u],tmp+a[u]);
}
int in[N];
int main(){
    //ree
    sf("%d",&n);
    mem(fst,-1);e=0;
    rep(i,1,n)sf("%d",&a[i]);
    rep(i,1,n-1){
        int u,v;sf("%d%d",&u,&v);
        add(u,v);add(v,u);
        in[u]++;
    }
    ans=-inf;
    for(int i=1;i<=n;++i)dp[i]=-100*INF;
    dfs(1,1);
    if(ans==-inf)puts("Impossible");
    else cout<<ans<<'\n';
}
//别人的做法。
#include<bits/stdc++.h>

using namespace std;

#define LL long long
#define MP(a,b) make_pair(a,b)
#define mem(a,b) memset(a,b,sizeof(a))
#define REP(i,a,b) for(int i=a;i<=b;++i)
#define FOR(i,a,b) for(int i=a;i<b;++i)
#define pii pair<int,int>
#define sf scanf
#define pf printf

const int maxn = 2e5;

int n, pre[maxn+5];
vector<int> G[maxn+5];
LL arr[maxn+5], sum[maxn+5];

char fg = 0;
LL ans;

LL dfs1(int x, int pp)
{
    pre[x] = pp, sum[x] = arr[x];
    for(int i=0; i<G[x].size(); ++i)
        if(G[x][i] != pp)
            sum[x] += dfs1(G[x][i], x);
    return sum[x];
}

LL dfs2(int x)
{
    vector<LL> tmp;
    LL res = sum[x];
    for(int i=0; i<G[x].size(); ++i)
    {
        if(G[x][i] != pre[x])
            tmp.push_back( dfs2(G[x][i]) );
    }
    int sz = tmp.size();
    if(sz == 0) return res;
    if(sz >= 2)
    {
        sort(tmp.begin(), tmp.end());
        if(fg==0 || tmp[sz-1]+tmp[sz-2]>ans)
            fg = 1, ans = tmp[sz-1]+tmp[sz-2];
    }
    return max(res, tmp[sz-1]);
}

int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int u, v;
    sf("%d", &n);
    REP(i,1,n) sf("%lld", arr+i);
    FOR(i,1,n)
    {
        sf("%d%d", &u, &v);
        G[u].push_back(v);
        G[v].push_back(u);
    }
    dfs1(1, 0);
    dfs2(1);
    if(fg) pf("%lld\n", ans);
    else pf("Impossible\n");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值