重生之 AtCoder Regular Contest 135 T1 题解

我胡汉三又回来啦!

 

  简单总结一下前段时间,大概就是OI失利之后学习,,,然后认真搞学习一段时间之后又慢慢松懈,,,最后还陷入了感情问题(?),,然后高考理综炸裂,,200+,,,比班级平均分都低了二十多分,,,比模拟考试最低一次都低了30几分,,,,,,唉然后就最后进了TJU。 目前是TJU算法竞赛的预备队成员,,反正结果已然如此,继续努力在这个还不错的平台继续努力~

  

  本次是寒假在家自主训练第一天的比赛,,,atcoder还是一如既往的风格,,全是数学,,,最后比赛前几分钟想到了t1正解,最后比赛结束才写完,,,a掉了,,,剩下的题,,,要是没有题解没有讲解我就不更了,,,水平不够,,补不上。。。。

 

  (LateX 真不咋会,,,虽然学了一小段时间,,但是平时应用还是不足)

题面

 

A - Floor, Ceil - Decomposition

There is an interger X written on a blackboard. You can do the operation below any number of times (possibly zero).

  · Choose an interger x written on the blackboard.

  · Erase one x from the blackboard and write two ner integers  

Find the maximum possible product of the integers on the blackboard after your operations,modulo 998244353

 

 

题目大意

  给定一个整数,可以将其擦掉,变成,(好丑)

  然后最后使得所有留下来的数乘积最大。

 

数据范围:

 

  0 ≤ X ≤ 1018

 

输入样例:

 

15

 

输出样例:

 

192

 

样例解释:

  将15变成(7,8)

  操作7,使得结果变成(3,4,8)

  操作4,使得结果变成(3,2,2,8)

  操作8,使得结果变成(3,2,2,4,4)

  最终用3x2x2x4x4=192

 

输入样例2:

3

输出样例2:

3

输入样例3:

100

输出样例3:

824552442

  最大的答案应该是 5856458868470016 取模后的结果如上

 

题解:

  首先是上来思考,对于偶数n来说,拆分的两个数乘积肯定是 n2/4 简单的数学不等式知识可以证明,凡是大于4的偶数,都应该进行拆分,使得最终结果乘积变得更大,而对于4本身,拆不拆分无所谓,不影响最终结果,对于2,不能拆分,否则会使得结果变小 (显然)

  然后考虑奇数,首先下取整+上取整,可以保证拆分出来的两个数的和等于原本的数,那么只需要让 2x+1 < x*(x+1) ,可以解得,对于所有大于3的奇数,都应该进行拆分,使得结果更大,而3则不需要拆分。

  

  那么其实我们能够想到,最终留在黑板上的数字,应该是由2,3两个数字组成的序列。 (我们考虑把所有的4都拆成两个2,来对问题进行归一化)

而且刚刚还提到了一个性质,在拆分的过程中,和不变,那么就变成统计一个数能够拆分成多少个2,多少个3,然后最终结果就是快速幂取模运算。

  

  对于这个问题,我想了很久,最终把表格列出来进行打表找规律(菜是原罪)

 

 

 

  可以发现,,对于2的幂次来说,应该最终拆分成 x/2 个 2 和 0 个 3 

  我们以这样的数作为分界线(以8-16为例),可以看到,2的数量先是每个减少一个,直到0,然后再每个增加两个,直到下一个2的幂次

 

 

 对于3来说,规律更加明显,对于每个2的幂次的数来说,3的个数都是0,然后先逐个+1,再逐个-1

 

 

 

 

那么最后结合快速幂,就可以得到最终正确的答案啦!

 

代码:

 

 

复制代码
#include<bits/stdc++.h>
#define re register
#define ll long long
#define inc(i,j,k) for(re int i=j;i<=k;i++)
#define dec(i,j,k) for(re int i=j;i>=k;i--)
using namespace std;
inline int read()
{
    re int x=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9') {if(ch=='-') f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9') {x=x*10+(ch^48); ch=getchar();}
    return x*f;
}
ll x;
ll cnt2,cnt3;
ll ans=1;
ll mod = 998244353;
ll qmm(ll a,ll b)
{
    ll res=0;
    while(b)
    {
        if(b&1)
            res=(res+a)%mod;
        a<<=1;
        b>>=1;
    }
    return res;
}
ll qpm(ll x,ll p)
{
    ll res=1;
    while(p)
    {
        if(p&1) res=res*x%mod;
        p>>=1;
        x=x*x%mod;
    }
    return res;
}
int main()
{
    cin>>x;
    if(x==1)
    {
        cout<<1<<endl;
        return 0;
    }
    ll res=1;
    int cnt=0;
    while(1)
    {
        if(res*2<=x)
        {
            res=res*2;
            cnt++;
        }
        else break;
    }
    ll r=x-res;
    ll base=res/2;
    if(r<=base)
    {
        cnt2=base-r;
        cnt3=r;
    }
    else
    {
        cnt2=(r-base)*2;
        cnt3=base-(r-base);
    }
//    cout<<cnt2<<" "<<cnt3<<endl;
    ans=qmm(ans,qpm(2,cnt2));
    ans=qmm(ans,qpm(3,cnt3));
    cout<<ans<<endl;
}
复制代码

 

posted @   ZzTzZ  阅读(118)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示