XTU Monthly, April 2014

本文精选了算法、编程技术及应用领域的多个实例,包括解决特定问题的策略、数学原理、编程语言特性等,旨在深入探讨如何高效实现目标,提供实用的技术解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:XTU Monthly, April 2014

A.Number

题意:0通过+1,-1,*2操作得到n(10^18)的最小方案数

思路:倒着看,偶数必然由*2得到,奇数由+1或-1得到,开个map存一下算过的

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
using namespace std;
typedef long long LL;
map<LL,int>mp;
LL solve(LL n){
    if(mp[n]!=0) return mp[n];
    if(n==0) return mp[n]=0;
    else if(n==1) return mp[n]=1;
    if(n&1) return mp[n]=min(solve(n+1),solve(n-1))+1;
    else return mp[n]=solve(n/2)+1;
}
int main(){
    LL n;
    mp.clear();
    while(scanf("%I64d",&n)!=EOF){
        printf("%I64d\n",solve(n));
    }
    return 0;
}

B.Lucky Wheel

题意:转盘1/2的概率无奖,1/8一等奖,1/8二等奖,1/8三等奖,1/8优秀奖,求x次一等奖,y次二等奖的期望

思路:用dp[i][j]表示i次一等奖,j次二等奖的期望

dp[i][j] = 1 + dp[i][j]  * 3/4 + dp[i-1][j] * 1/8 + dp[i][j-1] * 1/8

dp[i][j] = 4 + (dp[i-1][j] + dp[i][j-1]) * 1/2

暴力处理一下就出来了

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
using namespace std;
typedef long long LL;
#define maxn 1010
double dp[maxn][maxn];
int main(){
    for(int i=0;i<maxn;i++)
        dp[0][i]=8*i,dp[i][0]=8*i;
    for(int i=1;i<maxn;i++){
        for(int j=1;j<maxn;j++)
            dp[i][j]=4.0+(dp[i-1][j]+dp[i][j-1])/2.0;
    }
    int x,y;
    while(scanf("%d%d",&x,&y)!=EOF){
        printf("%.6lf\n",dp[x][y]);
    }
    return 0;
}

C.A+B

题意:求只包含a,b数字的序列和为n的方案数

思路:扩展欧几里得求出最小解的情况x0,y0,在保证都大于等于零的情况下,可以变换lcm(a,b)(即x0+=lcm(a,b)/b,y0-=lcm(a,b)/a)

所以总的方案数为 y0*b/lcm(a,b)+1 .     a=b的时候特判

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
using namespace std;
typedef long long LL;
LL exgcd(LL a,LL b,LL &x,LL &y){
    if(b==0){
        x=1,y=0;
        return a;
    }
    else{
        LL ans=exgcd(b,a%b,x,y);
        LL tmp=x;
        x=y;
        y=tmp-a/b*y;
        return ans;
    }
}
LL gcd(LL a,LL b){
    if(b==0) return a; return gcd(b,a%b);
}
LL lcm(LL a,LL b){
    return a/gcd(a,b)*b;
}
int main(){
    LL a,b,x,y,c;
    while(scanf("%I64d%I64d%I64d",&a,&b,&c)!=EOF){
        LL g=gcd(a,b);
        if(c%g!=0){
            printf("0\n");
            continue;
        }
        else if(a==b){
            printf("%d\n",(c%a)==0 );
        }
        else{
            a/=g,b/=g,c/=g;
            exgcd(a,b,x,y);
            x*=c; x=(x%b+b)%b;
            a*=g,b*=g,c*=g;
            LL x0=x,y0=(c-a*x)/b;
            if(y0<0){
                printf("0\n");
                continue;
            }
            LL l=lcm(a,b);
            printf("%I64d\n",b*y0/l+1);
        }
    }
    return 0;
}

D.Hexa Kill

题意:给出n个物品,m种限制,以及n个物品分别第几个被选所消耗的能量,以及m对限制(x,y)表示x在y之后被选,求最小消耗

思路:喵似是图论,不会


E.Tree

题意:有根树每个节点有个权值,一开始都是0。 你有这么两种操作。
操作1: 你可以使某个节点加上一个值v(1≤v≤100),那么这个节点的儿子就会加上2v,它儿子的儿子就加上3v...
操作2: 询问一个节点的权值。

思路:线段树。更新一个深度为d节点,它的儿子深度为dn,节点值为x+(dn-d+1)*v=x+dn*v-d*v+v,d*v是常数 ( by 小建建)

// by qqspeed
#include <stdio.h>
#include <string.h>
#include <vector>
#include <algorithm>
using namespace std;
#pragma comment(linker,"/STACK:102400000,102400000")

inline int input(){
    int ret=0;bool isN=0;char c=getchar();
    while(c<'0' || c>'9'){
        if(c=='-') isN=1;
        c=getchar();
    }
    while(c>='0' && c<='9'){
        ret=ret*10+c-'0';
        c=getchar();
    }
    return isN?-ret:ret;
}

typedef long long ll;
#define N 100005
#define L t<<1
#define R t<<1|1

int t,n;
vector<int>e[N];
int op,x,y,q;
int cnt;
int to[N],rTo[N],r,dis[N],last[N];

inline void dfs(int now,int pre){
    dis[now] = dis[pre]+1;
    to[now]=cnt;
    rTo[cnt]=now;
    cnt++;
    for(int i=0;i<e[now].size();i++){
        dfs(e[now][i],now);
    }
    last[now]=cnt-1;
}

struct node{
    int l,r;
    ll v1,v2;
    void init(int _l,int _r,ll _v1,ll _v2){
        l=_l,r=_r;
        v1=_v1,v2=_v2;
    }
}root[N<<2];

inline void push_down(int t){
    root[L].v1+=root[t].v1;
    root[R].v1+=root[t].v1;
    root[L].v2+=root[t].v2;
    root[R].v2+=root[t].v2;
    root[t].v1=root[t].v2=0;
}
inline void build(int t,int x,int y){
    root[t].init(x,y,0,0);
    if(x!=y){
        int mid=(x+y)>>1;
        build(L,x,mid),build(R,mid+1,y);
    }
}
inline void Add(int t,int x,int y,ll v1,ll v2){
    int l=root[t].l,r=root[t].r;
    if(l==x && r==y){
        root[t].v1+=v1;
        root[t].v2+=v2;
        return;
    }
    push_down(t);
    int mid=(l+r)>>1;
    if(y<=mid) Add(L,x,y,v1,v2);
    else if(x>mid) Add(R,x,y,v1,v2);
    else{
        Add(L,x,mid,v1,v2);
        Add(R,mid+1,y,v1,v2);
    }
}
inline ll query(int t,int x){
    int l=root[t].l,r=root[t].r;
    if(l==r){
        return root[t].v2+root[t].v1*dis[rTo[l]];
    }
    push_down(t);
    int mid=(l+r)>>1;
    if(x<=mid) return query(L,x);
    else return query(R,x);
}
int main(){
    t=input();
    while(t--){
        n=input();
        for(int i=0;i<=n;i++) e[i].clear();
        cnt=1;
        for(int i=1;i<=n;i++){
            x=input();
            if(x==0) r=i;
            else e[x].push_back(i);
        }
        dis[0]=0;
        dfs(r,0);
        build(1,1,cnt);
        q=input();
        while(q--){
            op=input();
            if(op==2){
                x=input();
                printf("%I64d\n",query(1,to[x]));
            }
            else{
                x=input();
                y=input();
                ll v1=y;
                ll v2=(1-dis[x])*y;
                y=last[x];
                x=to[x];
                Add(1,x,y,v1,v2);
            }
        }
    }
    return 0;
}



评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值