2018 BUPT Winter Training #1 div.1

17 篇文章 0 订阅
12 篇文章 0 订阅

修电脑回来已经三点了…如果多一个半小时应该能够多写一题两题的,说到底还是水平太菜..
可能有空会补C.E.X三道题,G题待定

A - One Bomb

题意 只有一个炸弹可以消去i行j列上的所有的墙,问能否消去所有的墙。
思路:统计行列wall总数,在(i,j)上放置一个炸弹,iswall表示二元谓词判断(i,j)是否是墙,消去的墙的数目 des=row[i]+col[j]iswall(i,j)

#include <cstdio>
char map[1005][1005];
int r[1005]={0},c[1005]={0};
int main(){
    int n,m,ar=0,ac=0,tot=0;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%s",map[i]+1);
        for(int j=1;map[i][j];j++){
            if(map[i][j]=='*'){
                r[i]++;
                c[j]++;
                tot++;
            }
        }
    }
    for(int i=1;i<=n&&!ar;i++){
        for(int j=1;j<=m&&!ar;j++){
            if(r[i]+c[j]-(map[i][j]=='*')==tot)ar=i,ac=j;
        }
    }
    if(ar)printf("YES\n%d %d",ar,ac);
    else printf ("NO");
}

B -Vacations

每天给一个数字:0.只能休息(我们假设这相当于在第i个位置填入0,以下同理);1.可以填入1;2.可以填入2;3.既可以填入1也可以填入2。
要求1和2不能相邻
那么相当于求一个字符串,这个字符串中0的数目最少,问最少的0的数目。
这就是经典的字符串动态规划问题了:
设dp[i][j]是在第i个位置填入数字j时不是0的最大总数.那么

dp[i][0]=max(dp[i1][0],dp[i1][1],dp[i1][2])dp[i][1 or 2]={maxdp(dp[i1][0],dp[i1][2 or 1])+1 [i][0] 

#include <cstdio>
#include <algorithm>
using namespace std;
int dp[105][3]={0};
int main(){
    int n,toda;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&toda);
        if(toda==1||toda==3)dp[i][2]=max(dp[i-1][1],dp[i-1][0])+1;
        if(toda==2||toda==3)dp[i][1]=max(dp[i-1][2],dp[i-1][0])+1;
        dp[i][0]=max(dp[i-1][0],max(dp[i-1][1],dp[i-1][2]));
        if(toda==0)dp[i][1]=dp[i][2]=dp[i][0];
    }
    printf("%d",n-max(dp[n][0],max(dp[n][1],dp[n][2])));
}

D - Lorenzo Von Matterhorn

这里编码的完全二叉树有一个特点:
设父节点 k=(a1a2a3...ap)2 则左孩子为 (a1a2a3...ap1)2 右孩子为 (a1a2a3...ap0)2 那么设孩子节点 k=(a1a2a3...ap)2 有父节点一定为 k=(a1a2a3...ap1)2

#include <iostream>
#include <map>
typedef long long ll;
using namespace std;
map<ll,ll> tree;
int main(){
    ios::sync_with_stdio(false);
    int p,a,b;ll s,u,v,w,ans;
    cin>>p;
    while(p--){
        cin>>s>>u>>v;
        w=ans=0;
        if(s==1)cin>>w;
        while(u!=v){
            if(u>v)ans+=(tree[u]+=w),u>>=1;
            else ans+=(tree[v]+=w),v>>=1;
        }
        if(s==2)cout<<ans<<endl;
    }
}

F - PLEASE

设三个概率分别为 ln , mn , rn
根据对称性有 ln=rn
根据概率性质有 ln+rn+mn=1 ln=rn=1mn2
所以

mn=12ln1+12rn1=ln1=1mn12

设分子为 an ,分母为 bn ,有 mn=anbn ,且 a0=1,b1=1
代入上式得
anbn=bn1an12bn1

易知 bn=2n1,an+an1=bn1=2n2
an+x2n1=(an1+x2n2),x=13,cn=an+x2n1
an132n1=13(1)n1

整理得到最终结果:
an=13(2n1(1)n1)

数学推导完毕,现在是数据的求法:
设常数2关于1e9+7的逆元i2,常数3关于1e9+7的逆元i3.谓词函数isodd(i)
有:
2n=2an%modanbn=2n/2%mod=i22n%modan=13(bn(1)n1)%mod=i3(bn+12isodd(n))%mod

#include <iostream>
#define mo 1000000007
#define i3 333333336
#define i2 500000004
using namespace std;
typedef long long ll;
ll ar[100005];
ll qp(ll x,ll y){ll a=1;while(y){if(y&1)a=a*x%mo;x=x*x%mo;y>>=1;}return a;}
int main(){
    ios::sync_with_stdio(false);
    int n,flag=0,odd=1;ll a=1,b=2,base,t;
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>ar[i];
        if(ar[i]>1)flag=1;
        if(odd)odd&=ar[i]&1;
    }
    for(int i=0;i<n&&flag;i++)b=qp(b,ar[i]);
    b=b*i2%mo;
    cout<<(b+mo+1-(odd<<1))*i3%mo<<"/"<<b<<endl;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值