其他分享
首页 > 其他分享> > day3

day3

作者:互联网

又是一年爆0日,绝胜比赛满盘输。

t1

给出一个二元组\((a,b)\),初始\(a=1,b=0\)(有点像exgcd?),有两种操作

  1. \((a,b)\rightarrow (a,b+1)\)
  2. \((a,b)\rightarrow (ab,b)\)

询问p次操作内,生成的数字在\([l,r]\)内的个数,\(p\leq 100,l,r\leq 10^8\)。

第一步是看出一个性质,问题类似于把b加到某个值,中途乘上\(1,2,...,b\),总乘上的个数+b不能超过p。

第二步是发现质因子为\(1,..,b\)内质数,且在\([l,r]\)范围的数字很少,据出题人估计不多,应该也就几百万,这个爆搜搞出来。

第三步是想到去递推这个方案数,但显然我们要保证次数在p内,于是设\(f[i]\)表示为a数字i的最小操作次数,显然数字可以到\(10^8\),我们需要离散化到数组\(a[]\)中,然后\(f[i]\)意思为第i个数字的最小操作次数,特别地,这个操作次数先不考虑操作1,

其实这个方程是压了维,应该还要表现一维,表示b为多少,但这不重要,于是顺序枚举b,然后从小到大枚举\(i\),有转移方程\(f[k]=min(f[k],f[i]+1)(a_ib=a_k)\),顺序枚举根据完全背包的理论,也表现了一个b被选择了多次,然后对于被更新的每个k,查看\(f_k+b\)与p的关系,查看其是否能被计算入答案(如果k已经被计算进答案忽略这步操作,所以需要开一个桶),这样就恰好把每个数字在每个b下的最少次数给求出来,然后不重不漏地把它们计算进答案即可,时间复杂度太玄学,不予考虑。

参考代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define il inline
#define ri register
#define ll long long
#define Size 5000000
using namespace std;
bool check[150],is[Size];
int prime[150],pt,
    a[Size],at,l,r,
    f[Size];
void dfs(int,int);
il void prepare(int);
int main(){int p,ans(0);
    scanf("%d%d%d",&l,&r,&p);
    prepare(p),a[at=1]=1;
    dfs(1,pt),sort(a+1,a+at+1);
    memset(f,0x3f,sizeof(f)),f[1]=0;
    for(int i(2),j,k;i<=p;++i)
        for(j=k=1;j<=at;++j){
            while(a[j]*i>a[k]&&k<=at)++k;
            if(k>at)break;
            if(a[j]*i==a[k])f[k]=min(f[j]+1,f[k]);
            if(f[k]+i<=p&&a[k]>=l&&!is[k])
                is[k]=true,++ans;
        }printf("%d",ans);
    return 0;
}
il void prepare(int n){
    for(int i(2),j;i<=n;++i){
        if(!check[i])prime[++pt]=i;
        for(j=1;j<=pt&&prime[j]*i<=n;++j){
            check[i*prime[j]]=true;
            if(!(i%prime[j]))break;
        }
    }
}
void dfs(int x,int b){
    if(!b)return;dfs(x,b-1);
    while((ll)x*prime[b]<=r)
        x*=prime[b],a[++at]=x,dfs(x,b-1);
}

t2

有一个\(n\times m\)的网格图,已经给出哪里是空地,哪里是障碍物,保证每行每列不超过一个障碍物,而且一个障碍物周围8个没有其他障碍物,现在随意选择两个位置A,B(显然必须为空地),允许重合,询问从A到B的最短路径的数学期望,\(n,m\leq 2000\)。

设空地的位置有tot个,所有空地对的最短路径之和为sum,那么答案就为\(\frac{sum}{tot^2}\),后者显然很好统计,关键在前者。

我们不妨忽略障碍物和其阻挡效果,求出位置(i,j)到所有位置的最短距离之和\(hl\)显然为\(O(n^2)\),而对于求出位置\((i,j+1)\)的距离值和就为\(hl-(m-j)n+jhl\),同理求位置\((i+1,j)\)的所有最短距离之和为\(hl-(n-i)m+ihl\),因此我们就可以递推出所有位置到其他位置的最短距离之和。

考虑进障碍物,忽略其阻挡效果,发现只要是空地就加上该位置的hl,否则减去hl,这样做,我们就减多了障碍物到障碍物的最短距离之和,没关系,障碍物最多只有\(n\)个,我们还是可以暴力求出来。

因此就可以算出所有空地到其他空地最短距离可以"穿过障碍物"的和,现在考虑如何计算因为障碍物阻挡而绕路的情况,很难发现规律,如下图

标签:障碍物,短距离,int,位置,day3,hl,空地
来源: https://www.cnblogs.com/a1b3c7d9/p/11293713.html