AcWing打卡day3

1.激光炸弹
题意:给一个R×R的炸弹,和n个宝藏的坐标和价值,求可以炸掉的最大价值
思路:建立一个二维数组的前缀和,s[i][j]代表者在这里插入图片描述
所以s[i][j]=s[i][j]+s[i-1][j]+s[i][j-1]-s[i-1][j-1];
对于半径为r的正方形的价值为,s[i][j]-s[i-r][j]-s[i][j-r]+s[i-r][j-r];

核心代码`

for(int i=1;i<=5001;i++)
    {
        for(int j=1;j<=5001;j++)
        {
            qzh[i][j]=qzh[i][j]+qzh[i-1][j]+qzh[i][j-1]-qzh[i-1][j-1];
        }
    }
    int ans=0;
for(int i=r;i<=5001;i++)
    {
        for(int j=r;j<=5001;j++)
        {
            ans=max(ans,qzh[i][j]-qzh[i-r][j]-qzh[i][j-r]+qzh[i-r][j-r]);
        }
    }

2.约数之和
题目:求A^B的所有约数和是多少
思路:利用唯一分解定理约数和定理分治递归求解
pn代表p的n次方
计算1+p+p1+······+pn可分为两类
n为奇数,有偶数项
在这里插入图片描述
n为偶数,有奇数项,当独拿出最后一项,然后按偶数项处理
核心代码

ll solve(ll p,ll c)
{
    if(c==0)return 1;
    if(c&1)
    {
        return ((1+ksm(p,(c+1)>>1))*solve(p,(c-1)>>1))%mod;
    }
    else
    {
        return ((1+ksm(p,c>>1))*solve(p,(c>>1)-1)+ksm(p,c))%mod;
    }
}

3.石子合并
题意:给你n堆石子,让你合并到只有一堆石子,每次合并两堆石子的的代价是两队的石子的权值之和,求最小和并代价
思路:区间dp模板题,dp[i][j]=min(dp[i][k]+dp[k+1][j]+s[j]-s[i-1])
核心代码

for(int len=2;len<=n;len++)
    {
        for(int i=1;i+len-1<=n;i++)
        {
            int r=i+len-1;
            dp[i][r]=0x3f3f3f3f;
            for(int j=i;j<r;j++)
            {
                dp[i][r]=min(dp[i][r],dp[i][j]+dp[j+1][r]+s[r]-s[i-1]);
            }
        }
    }

4.启示录
题意:有三个连续的6的是魔鬼数,如666,1666,6663,16666,6660666,求第x个魔鬼数
思路:数位dp+二分+记忆化搜索
核心代码

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
ll dp[30][30];
ll num[30];
ll dfs(ll pos,ll limit,ll state)
{
    if(pos==-1)
    {
        if(state==3)return 1;
        else return 0;
    }
    if(!limit&&dp[pos][state]!=-1)return dp[pos][state];
    ll up=limit?num[pos]:9;
    ll sum=0;
    for(ll i=0; i<=up; i++)
    {
        ll nextState=0;
        if(state==3)
        {
            nextState=3;
        }
        else if(state==2&&i==6)
        {
            nextState=3;
        }
        else if(state==1&&i==6)
        {
            nextState=2;
        }
        else if(state==0&&i==6)
        {
            nextState=1;
        }
        sum+=dfs(pos-1,limit&&i==up,nextState);
    }
    if(!limit)dp[pos][state]=sum;
    return sum;
}
ll solve(ll x)
{
    int cnt=0;
    while(x)
    {
        num[cnt++]=x%10;
        x/=10;
    }
    return dfs(cnt-1,1,0);
}
int main()
{
    memset(dp,-1,sizeof(dp));
    int t;
    cin>>t;
    while(t--)
    {
        ll x;
        cin>>x;
        ll l=1,r=1e10,ans=1,mid;
        while(l<=r)
        {
            mid=(l+r)>>1;
            if(solve(mid)>=x)
            {
                ans=mid;
                r=mid-1;
            }
            else
            {
                l=mid+1;
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值