题意: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之后被选,求最小消耗
思路:喵似是图论,不会
题意:有根树每个节点有个权值,一开始都是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;
}