HRBU_20211119训练

E - Justifying the Conjecture

题意:

给定 n n n,问 n n n是否能由一个素数 x x x和一个非素数 y y y相加得到?

做法:

思维题,当 n < = 5 n<=5 n<=5时,首先素数有2,3,5,非素数有1,4;根本无法构成题目要求所以直接输出 − 1 -1 1 ,接下来就是大于5的情况了,首先如果是个偶数,那么他必然可以分成 2 + n − 2 2+n-2 2+n2,所有的偶数都是
2的倍数,所以后一个数一定不是素数,其次就是奇数,保守估计了一下直接拆成 3 + n − 3 3+n-3 3+n3

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const ll N=1e8+5;

//int prime[N];
//bool visit[N];

/*void Prime()
{
    int cnt=0;
    memset(visit,false,sizeof(visit));
    for (int i = 2; i <= N; i++)
    {
        if (!visit[i])
        {
            prime[++cnt] = i;
        }
        for (int j = 1; j <=cnt; j++)
        {
            if(i*prime[j]>maxn)
                break;
            visit[i*prime[j]]=true;
            if(i%prime[j]==0)
                break;
        }
    }
}*/

int main()
{
    int T,n;
    //Prime();
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        if(n<=5)
            cout<<-1<<endl;
        else
        {
            if(n&1)
                cout<<3<<" "<<n-3<<endl;
            else
                cout<<2<<" "<<n-2<<endl;
        }
    }
    return 0;
}

F - Keeping Rabbits

题意:

初始给出 n n n个重量,假设总和为 s u m sum sum,每个兔子每天的体重增加1的概率是他占所有的兔子的总的重量的比例。问 k k k天之后每只兔子的重量的期望值是多少?

做法:

数学期望计算,我们知道k天之后所有的兔子的总的重量增加为k,那么我们现在就是要把这 k k k分配到 n n n只兔子上面。根据题目给定公式
在这里插入图片描述
然后进一步推出 a [ i ] = a [ i ] + k ∗ ( a [ i ] ∗ k / s u m ) a[i]=a[i]+k∗(a[i]∗ k/sum) a[i]=a[i]+k(a[i]k/sum)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
ll a[maxn],s;
int main()
{
    ios::sync_with_stdio(false);
    int T,n,k;
    scanf("%d",&T);
    while(T--)
    {
        s=0;
        scanf("%d%d",&n,&k);
        for(int i=1; i<=n; i++)
            scanf("%lld",&a[i]),s+=a[i];
        for(int i=1; i<=n; i++)
        {
            printf("%.8lf",a[i]+a[i]*k*1.0/s);
            if(i!=n)
                printf(" ");
        }
        printf("\n");
    }
    return 0;
}

B - Fixing Banners

题意:

从6个字符串里面各取一个字符,问是否可以可以拼接成一个字符串 ′ h a r b i n ′ 'harbin' harbin

做法:

暴力美学,直接用map去存每一个字符且标出位置,然后dfs跑每一个给定的字符,最后判断一下输出。也可以预处理然后全排列。全排列的话这位dalao讲得好传送门

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
map<char,int> mp;
bool pos[10][10],vis[10];
int ans;
string s[10];

void init()
{
    memset(pos,false,sizeof(pos));
    for(int i=0;i<6;i++)
    {
        for(int j=0;j<s[i].size();j++)
        {
            if(mp.count(s[i][j])==0)
                continue;
            else
                pos[i][mp[s[i][j]]]=true;
        }
    }
    memset(vis,false,sizeof(vis));
}

void dfs(int x)
{
    if(x==6||ans==1)
    {
        ans=1;
        return;
    }
    for(int i=0;i<6;i++)
    {
        if(vis[i]||!pos[i][x+1])
            continue;
        else
        {
            vis[i]=true;
            dfs(x+1);
            vis[i]=false;
        }
    }
}

int main()
{
    ios::sync_with_stdio(false);
    int T,n,k;
    mp.clear();
    mp['h']=1,mp['a']=2,mp['r']=3,mp['b']=4,mp['i']=5,mp['n']=6;
    cin>>T;
    while(T--)
    {
        ans=0;
        for(int i=0;i<6;i++)
            cin>>s[i];
        init();
        dfs(0);
        if(ans)
            cout<<"Yes"<<endl;
        else
            cout<<"No"<<endl;
    }
    return 0;
}

D - Interesting Permutation

题意:

现在你手上有四个数组 a , f , g , h a,f,g,h a,f,g,h,但是你只确定一个数组h里的元素。巧的是你还知道

  • 对于每一个 1 < = i < = n 1<=i<=n 1<=i<=n,都有 f [ i ] = m a x ( a 1 , a 2..... , a i ) f[i]=max(a1,a2.....,ai) f[i]=max(a1,a2.....,ai)
  • 对于每一个 1 < = i < = n 1<=i<=n 1<=i<=n,都有 g [ i ] = m i n ( a 1 , a 2..... , a i ) g[i]=min(a1,a2.....,ai) g[i]=min(a1,a2.....,ai)
  • 对于每一个 1 < = i < = n 1<=i<=n 1<=i<=n,都有 h [ i ] = f [ i ] − g [ i ] h[i]=f[i]-g[i] h[i]=f[i]g[i]

问你是否可以通过 h h h数组推出原来 a a a数组有多少种合法排列呢?最后的答案需要对 1 e 9 + 7 1e9+7 1e9+7取模

做法:

啥叫a的合法排列呢?就是你求出的a数组要能够再次构成h数组。其实没啥用OMO
首先咱来分析一下 h 的 合 法 性 h的合法性 h

  • h h h数组第一个数字必然是 0 0 0,因为 a [ 1 ] a[1] a[1]只有一个元素,最大最小都是自己,所以 h [ 1 ] = 0 h[1]=0 h[1]=0
  • h h h数组最后一个数字必然是 n − 1 n-1 n1,类似于上边,整个 a a a数组最大值是 n n n,最小值是 1 1 1,所以 h [ n ] = n − 1 h[n]=n-1 h[n]=n1
  • h h h数组必定 单 调 不 递 减 单调不递减 ,因为都是最大值减最小值,所以越往后h的值必定 越 来 越 大 越来越大 ,不可能会变小
    确定了h的合法性,再观察观察h的构成 h [ i ] = f [ i ] − g [ i ] = > h [ i ] = m a x ( a 1 , a 2..... , a i ) − m i n ( a 1 , a 2..... , a i ) h[i]=f[i]-g[i]=>h[i]=max(a1,a2.....,ai)-min(a1,a2.....,ai) h[i]=f[i]g[i]=>h[i]=max(a1,a2.....,ai)min(a1,a2.....,ai)。所以当 h [ i ] ! = h [ i − 1 ] h[i]!=h[i-1] h[i]!=h[i1]时必然是最值有改变(可能是最大值变了也可能是最小值变了)所以这里是两种情况;接下来 h [ i ] > h [ i − 1 ] h[i]>h[i-1] h[i]>h[i1]中间会有一个数字区间空出来,而我们需要做的只需要从这些数字中抽出来一个就能构成 a a a数组中的对应元素啦
    整理一下
    两个条件
  • h [ i ] = = h [ i − 1 ] , a n s = a n s ∗ c n t , c n t − − h[i]==h[i-1],ans=ans*cnt,cnt-- h[i]==h[i1],ans=anscnt,cnt
  • h [ i ] > h [ i − 1 ] , a n s = a n s ∗ 2 , c n t + = ( h [ i ] − h [ i − 1 ] − 1 ) h[i]>h[i-1],ans=ans*2,cnt+=(h[i]-h[i-1]-1) h[i]>h[i1],ans=ans2,cnt+=(h[i]h[i1]1)
    最后不要忘记了取模呀!
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const int mod=1e9+7;
int n,m,q;
ll h[maxn];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int flag=0;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%lld",&h[i]);
        if(h[1]!=0||h[n]!=n-1)
        {
            printf("0\n");
            continue;
        }
        ll ans=1,cnt=0,maxx=0;
        for(int i=2;i<=n;i++)
        {
            maxx=max(h[i],maxx);
            if(h[i]<maxx)
            {
                flag=1;
                break;
            }
            if(h[i]>h[i-1])
            {
                ans=ans*2%mod;
                cnt+=(h[i]-h[i-1]-1);
            }
            else if(h[i]==h[i-1])
            {
                ans=ans*cnt%mod;
                cnt--;
            }
        }
        if(flag)
            printf("0\n");
        else
            printf("%d\n",(ans+mod)%mod);
    }
    return 0;
}
每日小结:

终于呀!不欠账了呀!nice!一周结!周赛前疯狂补题,(╥╯^╰╥)最近又开始瞎浪了,今天好说好歹是给自己整起来了,没有咸鱼的一天!充实的一匹!最近的Linux学的有点舒服,主要是上学期的忘的差不多了,啥也不会了QAQ还是一条老咸鱼呀,7天我们也要打这半年来的最后一场了,加油!愿明天的朝阳能给予我开心过完一天的好运呀!Thanks♪(・ω・)ノ

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值