2018CCPC吉林赛区(重现赛)补题部分——F线段树待补

A - The Fool

数论分块暴力求和

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int mod=1e9+7;
int main()
{
    //IO;
    int T=1;
    cin>>T;
    for(int ca=1;ca<=T;ca++)
    {
        int n;
        cin>>n;
        ll s=0;
        for(int l=1,r;l<=n;l=r+1)
        {
            r=n/(n/l);
            s=(s+1ll*(r-l+1)%2*(n/l))%2;
        }
        if(s%2) printf("Case %d: odd\n",ca);
        else printf("Case %d: even\n",ca);
        
    }
    return 0;
}

B - The World

这题就离谱??? 不明白下面的一二两个设定?很反直觉啊啊啊

  • 12:00 AM 是凌晨十二点
  • 12:00 PM 是中午十二点
  • h=0输出12
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int mod=1e9+7;
map<string,int> mp;
int main()
{
    //IO;
    int T=1;
    cin>>T;
    mp["Beijing"] = 8;
    mp["Washington"] = -5;
    mp["London"] = 0;
    mp["Moscow"] = 3;
    for(int ca=1;ca<=T;ca++)
    {
        int h,m;
        string op,from,to;
        scanf("%d:%d",&h,&m);
        cin>>op>>from>>to;
        if(h==12) h=0;
        if(op=="PM") h+=12;
        h+=mp[to]-mp[from];
        int f=0;
        string now;
        if(h<0) 
        {
            f=-1;
            h+=24;
        }
        else if(h>=24)
        {
            f=1;
            h-=24;
        }
        if(h>=12) 
        {
            h-=12;
            now="PM";
        }
        else
            now="AM";
        if(h==0) h+=12;
        // 输出
        printf("Case %d: ",ca);
        if(f==-1) 
            printf("Yesterday %d:%02d ", h, m);
        else if(f==0)
            printf("Today %d:%02d ", h, m);
        else 
            printf("Tomorrow %d:%02d ", h, m);
        cout<<now<<'\n';
    }
    return 0;
}

C - Justice

自己想的辣鸡代码
刚开始没思路于是想猜结论:只要和大于1就一定能够分成两组,因为它是以 1 2 k \frac{1}{2^k} 2k1为一份,怎么分组就贪心分一下,对于较大的k由于小数太小,没法存储,我当时想的是忽略这些值(k>25的时候小数已经非常小可能对答案没影响),于是写出了下面辣鸡代码wa了

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int mod=1e9+7;
const double eps=1e-14;
const int N=100010;
double two[110];
int ans[N];
int n;
struct node
{
    int k,id;
    bool operator<(const node& o) const 
    {
        return k<o.k;
    }
}q[N];
int main()
{
    //IO;
    int T=1;
    cin>>T;
    two[0]=1.0;
    for(int i=1;i<=100;i++) two[i]=two[i-1]/2.0;
    for(int ca=1;ca<=T;ca++)
    {
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            cin>>q[i].k;
            q[i].id=i;
        }
        sort(q+1,q+1+n);
        double s=0.0;
        for(int i=1;i<=n;i++)
        {
            if(q[i].k>=100) 
            {
                ans[q[i].id]=1;
                continue;
            }
            if(s+eps>0.5) 
                ans[q[i].id]=1;
            else
                ans[q[i].id]=0;
            s+=two[q[i].k];
        }
        if(s+eps>1.0) 
        {
            printf("Case %d: YES\n",ca);
            for(int i=1;i<=n;i++)  
                cout<<ans[i];
            cout<<'\n';
        }
        else
            printf("Case %d: NO\n",ca);
    }
    return 0;
}

正解
我们需要凑一个 1 2 \frac12 21,或者2个 1 4 \frac14 41,或者4个 1 8 … \frac18\dots 81
不难发现如果当前需要凑 c n t cnt cnt 1 2 k \frac1{2^k} 2k1,那么如果现在没有 1 2 k \frac1{2^k} 2k1,我们不得不用 1 2 j ( j > k ) \frac1{2^j}(j>k) 2j1(j>k)来凑,不难发现我们现在需要凑 c n t × 2 j − k cnt×2^{j-k} cnt×2jk 1 2 j \frac1{2^j} 2j1

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=100010;
struct node
{
    int k,id;
    bool operator<(const node&o) const 
    {
        return k<o.k;
    }
}q[N];
int ans[N];
int n;
int main()
{
    //IO;
    int T=1;
    cin>>T;
    for(int ca=1;ca<=T;ca++)
    {
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            ans[i]=0;
            cin>>q[i].k;
            q[i].id=i;
        }
        sort(q+1,q+1+n);
        bool ok=0;
        int pre=1;
        int cnt1=1,cnt2=1;
        for(int i=1;i<=n;i++)
        {
            while(cnt1+cnt2<=n-i+1&&pre<q[i].k)//少个+1都会wa 感觉数据有点诡异啊
            {
                cnt1*=2;
                cnt2*=2;
                pre++;
            }
            if(cnt1+cnt2>n-i+1) break;
            
            if(cnt1>0)
            {
                cnt1--;
                ans[q[i].id]=1;
            }
            else
                cnt2--;   
            if(cnt1<=0&&cnt2<=0) 
            {
                ok=1;
                break;
            }
        }
        if(!ok) printf("Case %d: NO\n",ca);
        else
        {
            printf("Case %d: YES\n",ca);
            for(int i=1;i<=n;i++) cout<<ans[i];
            cout<<'\n';
        }
    }
    return 0;
}

D - The Moon

一看就是个概率dp的题,由于自己概率dp的题写的太少了,然后就写不出来,看的题解。

f i f_i fi是当 q = i q=i q=i是的期望次数
f i = p ( 1 − q ) ( 1 + f q + 2 % ) + p q + ( 1 − p ) ( 1 + f q + 1.5 % ) f_i=p(1-q)(1+f_{q+2\%})+pq+(1-p)(1+f_{q+1.5\%}) fi=p(1q)(1+fq+2%)+pq+(1p)(1+fq+1.5%)
记忆化搜索即可

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int mod=1e9+7;
const int N=1010;
double f[N];
int p;
double dfs(int q)
{
    if(f[q]>=0) return f[q];
    if(q>=1000)
        return f[q]=100.0/(1.0*p);
    
    f[q]=(1.0*p/100.0)*(1.0-1.0*q/1000.0)*dfs(min(1000,q+20))
        +(1.0-1.0*p/100.0)*dfs(min(1000,q+15))
        +1.0;
    return f[q];
}
int main()
{
    //IO;
    int T=1;
    cin>>T;
    for(int ca=1;ca<=T;ca++)
    {
        for(int i=0;i<=1000;i++) f[i]=-1;;
        cin>>p;
        printf("Case %d: %.6lf\n",ca,dfs(20));
    }
    return 0;
}

F - The Hermit

这题非常巧妙啊
结论:对于第 i i i个站 [ i − r a d i + 1 , i − 2 ] [i-rad_i+1,i-2] [iradi+1,i2]范围的基站都能够接收到第 i i i个站的perfect signal
仔细想想可知道根据 i − r a d i + 1 ≤ i + 1 − r a d i + 1 + 1 i - rad_i + 1 ≤ i + 1 - rad_{i+1} + 1 iradi+1i+1radi+1+1条件,就能使 [ i − r a d i + 1 , i − 2 ] [i-rad_i+1,i-2] [iradi+1,i2]的基站满足条件。

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int mod=1e9+7;
const int N=100010;
int main()
{
    //IO;
    int T=1;
    cin>>T;
    for(int ca=1;ca<=T;ca++)
    {
        
        int n;
        cin>>n;
        int res=0;
        for(int i=1;i<=n;i++)
        {
            int a;
            cin>>a;
            res^=max(0,a-2);
        }
        printf("Case %d: %d\n", ca, res);
    }
    return 0;
}

I - Strength

贪心+模拟,1发A有点高兴。
先判断是否能够打死完对面的怪物,如果能够打完那么先用最小的代价把防御类型的干掉(只需找一个大于防御值的最小的攻击即可)
如果不能打死完,那么我们只需要用最大的攻击最小的即可,欺负弱小

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int mod=1e9+7;
const int N=100010;
int n,m;
int a[N];
int b[N];
bool st1[N],st2[N];
int main()
{
    //IO;
    int T=1;
    cin>>T;
    for(int ca=1;ca<=T;ca++)
    {
        memset(st1,0,sizeof st1);
        memset(st2,0,sizeof st2);
        vector<int> ak,df;
        cin>>n>>m;
        for(int i=1;i<=n;i++) cin>>a[i];
        sort(a+1,a+1+n);
        for(int i=1;i<=m;i++) cin>>b[i];
        for(int i=1;i<=m;i++)
        {
            int op;
            cin>>op;
            if(op) df.push_back(b[i]);
            else ak.push_back(b[i]);
        }
        sort(df.begin(),df.end());
        sort(ak.begin(),ak.end());
        int cnt=0;
        int j=1;
        for(auto t:df)
        {
            while(j<=n&&a[j]<t) j++;
            if(a[j]>=t) 
            {
                st1[j]=1;
                cnt++;
                j++;
            }
            else break;
        }
        
        int res1=0,res2=0;
        if(cnt==df.size())
        {
            int cnt=0,j=1;
            for(auto t:ak)
            {
                while(j<=n&&!st1[j]&&a[j]<t) j++;
                if(a[j]>=t)
                {
                    res1+=a[j]-t;
                    j++;
                    st2[j]=1;
                    cnt++;
                }
                else break;
            }
            if(cnt==ak.size())
            {
                for(int i=1;i<=n;i++)
                    if(!st1[i]&&!st2[i]) res1+=a[i];
            }
            else
            {
                res1=0;
                int j=n;
                for(auto t:ak)
                {
                    if(!st1[j]&&a[j]>=t) 
                    {
                        res2+=a[j]-t;
                        j--;
                    }
                    else break;
                }
            }
        }
        else
        {
            int j=n;
            for(auto t:ak)
            {
                if(a[j]>=t) 
                {
                    res2+=a[j]-t;
                    j--;
                }
                else break;
            }
        }
        printf("Case %d: %d\n", ca, max(res1, res2));
    }
    return 0;
}

F - Lovers

线段树待补

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值