每一年都奔走在自己热爱里

没有人是一座孤岛,总有谁爱着你

AtCoder Beginner Contest 300(E,F)

AtCoder Beginner Contest 300(E,F)

E (概率dp)

E

这个题意大致就是一开始有一个初始数x1,然后我们有一个骰子,最后得到的点数概率一样,为16,如果这一次得到的点数为i,那么x会变成i×x,问最后得到数n的概率为多少

先感性的分析一波,对于这六个数,除了1之外都可以改变x,那么我们可以不用考虑1得到的效果,毕竟不管得没得到1效果都是一样的,那么我们每一次投中的概率就是15

下面我给出证明

假设dp[i]是得到的数为i的概率,那么我们可以得到

dp[i]=16dp[i]+j=1n16dp[ij]

我把1和后面的数分开了

然后可以移项,把dp[i]放在一边,毕竟这个才是我们需要的

56dp[i]=j=1n16dp[ij]

然后把dp[i]的系数变成1,这样好看一点

dp[i]=j=1n15dp[ij]

这样,对于后面的非1数,得到的概率可以看成15

然后我看到一个很好的解法,很易懂,大佬博客

他是从1逐渐往后面找,每得到一个新的点,都会乘上这个概率,(然后还用上了记忆化)

只有找到了n才是正确的

幸好这些数都就算是最小的2最多也只有64多次,而且,每次找都不会往回找,而是一直找,而且不会进入死循环,但是这个想法真的好好,有点像dfs在不断的往前找,走了一步就加一的感觉,我自己最初的想法是把那个n分解成若干个2,3,5,但是这个也不太好些,因为还有4,6的情况,还不止,还要考虑顺序,感觉有点复杂

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include<cmath>
#include <unordered_map>
#include <array>
#include <cstring>
using namespace std;
#define int long long 
#define LL long long
#define ios  ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define inf 1e18
#define INF 1e18
#define mem(a,b) memset((a),(b),sizeof(a))
const int maxn=1e6+10;
const int mod=998244353;
int p;
int n;
unordered_map<int,int>f;
int ksm(int x,int p)
{
    int res=1;
    while (p)
    {
        if(p&1) res=res*x%mod;
        x=x*x%mod;
        p>>=1;
    }
    return res%mod;
}
int inv(int x)
{
    return ksm(x,mod-2);
}
int getf(int x)
{
    if(x>n) return 0;
    if(x==n) return 1;
    if(f.count(x))return f[x];
    int res=0;
    for (int i=2;i<=6;i++)
    {
        res=(res+getf(i*x))%mod;
    }
    res=res*p%mod;
    f[x]=res;
    return f[x];
}
signed main ()
{
    cin>>n;
    p=inv(5);
    int ans=getf(1);
    cout<<ans<<"\n";
    system ("pause");
    return 0;
}

F (二分)

F

这个题的大意是给你一个长度为n的只由x,o两个字符组成的字符串s,我们可以得到一个T字符串,T=m×s,我们可以从这个T里面,选出kx变成o,问最后我们可以得到最大的连续o的长度,而且,这道题还提醒了我们T里面的x的数量一定是够的(所以不存在没有足够k)

这个呢

我们可以先从第一个s看,对于l,r这一段,要把这一段都变成o的代价就是这一段里面x的数量,所以,我们可以预先把x的前缀数量记录下来

对于一个最长的o串,一定是有最左端点一定在第一个字符串上面,(这是最优的,后面的和它都是一样的,而且越前面越代表答案可能越大)

我们枚举最左端点

然后对于第一个字符串,找到一个有最右端点sum[r]sum[l]小于等于k,那么此时我们就已经获得了rl+1o了,如果我们要继续往后找第二个字符串的话,只有r等于n时才可以(不然不就是连最后一个都到不了,根本不需要考虑后面的)

对于往后找,我们先看了剩余的操作次数可不可以把字符串全部都变成o,这样把可以全部变成o的考虑

如果还有剩余,我们就去考虑,剩下的最远可以到哪一个位置

我之前一直在担心会不会操作不够,其实完全不用担心,如果我们对于这一次的最左端需要的操作数还不够,我们可以用到那些和这些没有关系的x上(毕竟题目已经告诉你了x的数量一定大于等于k,我之前就是考虑到这儿,每次都判断一下是不是等于k,结果wa

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include<cmath>
#include <unordered_map>
#include <array>
#include <cstring>
using namespace std;
#define int long long 
#define LL long long
#define ios  ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define inf 1e18
#define INF 1e18
#define mem(a,b) memset((a),(b),sizeof(a))
const int maxn=3e5+10;
const int mod=998244353;
int m,k,n;
string s;
int sum[maxn];
int find(int x,int last,int l,int r)
{
    int ans=-1;
    while (l<=r)
    {
        int mid=(l+r)>>1;
        int now=sum[mid]-last;
        if(now<=x)
        {
            ans=mid;
            l=mid+1;
        }
        else r=mid-1;
    }
    return ans;
}
signed main ()
{
    cin>>n>>m>>k;
    cin>>s;
    s=" "+s;
    for (int i=1;i<=n;i++)
    {
        int val=0;
        if(s[i]=='x') val=1;
        sum[i]=sum[i-1]+val;
    }
    int ans=0;
    for (int i=1;i<=n;i++)
    {
        int l=find(k,sum[i-1],i,n);
        if(l==-1) continue;
        int val=(l-i+1);
        int cnt=sum[l]-sum[i-1];
        if(l<n)
        {
            ans=max(ans,val);
        }
        else if(l==n)
        {
            int cha=(k-cnt)/sum[n];
            val+=min(cha,m-1ll)*n;
            if(cha<m-1ll)
            {
                int res=(k-cnt)-cha*sum[n];
                int pp=find(res,0,1,n);
                if(pp!=-1)
                {
                    val+=pp;
                }
            }
            ans=max(ans,val);
        }
    }
    cout<<ans<<"\n";
    system ("pause");
    return 0;
}
posted @   righting  阅读(21)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示