首页 > 其他分享 >20241023 模拟赛(GCD,包含,前缀,移动)

20241023 模拟赛(GCD,包含,前缀,移动)

时间:2024-10-25 15:45:33浏览次数:1  
标签:rnk GCD int ll pos mxn define 20241023 前缀

看题戳这里

总结

20min 自习。
上来 30min 先把 t1 写了。
然后 t2 没看明白,先打了个暴力?然后发现值域很离谱,dfs就行了。
t3 t4看了一眼就跑路了。

解析

A. GCD

难度:黄
注意到只有当 \(n=\) 素数 \(p\) 的正整数次幂时,有 \(f(n)=p\),
其他情况都是 \(f(n)=1\)。
所以用欧拉筛筛一遍的同时求答案就行了。


#include<bits/stdc++.h>
#define mxn 10000010
#define ll long long
#define pb push_back
using namespace std;
bool isp[mxn],vis[mxn];
ll a,b,cnt;
ll ans;
vector<ll> prime;
void euler(){
    isp[1]=1;
    for(int i=2;i<=b;i++){
        if(!isp[i]){
            prime.pb(i);
            for(ll j=i;j<=b;j*=i)
                if(j>=a)ans+=i,vis[j]=1;
            cnt++;
        }
        else if(i>=a&&!vis[i])ans++;
        for(int j=0;j<cnt&&i*prime[j]<=b;j++){
            isp[i*prime[j]]=1;
            if(i%prime[j]==0)break;
        }
    }
}
int main(){
    freopen("gcd.in","r",stdin);
    freopen("gcd.out","w",stdout);
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0); 
    cin>>a>>b;
    euler();
    cout<<ans;
    return 0;
}

B. 包含

难度:黄
一开始脑子抽了,居然想到了 01trie。
然后发现值域只到 \(10^6\),所以暴力 \(dfs\) 预处理,然后 \(O(1)\) 查询就行了。


#include<bits/stdc++.h>
#define ll long long
#define mxn 100010
using namespace std;
int n,m,mp[mxn*10];
int a[mxn],b;
void dfs(int x){
    if(mp[x])return;
    mp[x]=1;
    for(int i=0;i<=20;i++)
        if((x>>i)&1)
            dfs(x^(1<<i));
    return;
}
int main(){
    freopen("include.in","r",stdin);
    freopen("include.out","w",stdout);
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        dfs(a[i]);
    }
    for(int i=1;i<=m;i++){
        int x;cin>>x;
        if(mp[x])cout<<"yes\n";
        else cout<<"no\n";
    }
    return 0;
}

C. 前缀

难度:蓝
我们发现这玩意相当于一个序列自动机。
设 \(nxt[i][j][k]\) 为第 \(i\) 位上后面 \(2^k\) 个字符 \(j\) 的位置。
而 \(nxtlen[i][j][k]\) 为当前位置到后 \(2^k\) 个字符 \(j\) 的长度。
\(O(n\log n)\) 倍增预处理一下 \(nxt\) 和 \(nxtlen\) 就行了。
然后对于带数字的,还要搞一个高精除低精,处理出商和余数。
注意若无余数,最后一轮是不能跑满的。


#include<bits/stdc++.h>
#define mxm 100010
#define mxn 10010
#define mod 998244353
#define ll long long
using namespace std;
ll T,n,len,cnt[30];
ll first[mxn],last[mxn],nxt[mxn][30][20]; 
ll nxtlen[mxn][30][20];
char s[mxn],t[mxm];
int Int(char c){
    if(c=='*')return 26;
    else return c-'a';
}
void init(){
    memset(first,-1,sizeof(first));
    memset(last,-1,sizeof(last));
    for(int i=1;i<=len;i++){
        cnt[Int(s[i])]++,cnt[26]++;
        if(first[Int(s[i])]==-1)
            first[Int(s[i])]=i;
    }
    for(int i=0;i<=26;i++){
        last[i]=first[i];
        nxt[0][i][0]=first[i];
        if(first[i]!=-1)
            nxtlen[0][i][0]=first[i];
    }
    nxt[0][26][0]=1,nxtlen[0][26][0]=1;
    for(int i=len;i;i--){
        for(int j=0;j<=26;j++)
            nxt[i][j][0]=last[j];
        nxt[i][26][0]=(i==len)?1:i+1;
        last[Int(s[i])]=i;
        for(int j=0;j<=26;j++)
            if(cnt[j])
                nxtlen[i][j][0]=nxt[i][j][0]-i+len*(nxt[i][j][0]<=i);
    }
    for(int i=1;i<16;i++)
        for(int j=0;j<=len;j++)
            for(int k=0;k<=26;k++)
                nxt[j][k][i]=nxt[nxt[j][k][i-1]][k][i-1],
                nxtlen[j][k][i]=(nxtlen[j][k][i-1]+nxtlen[nxt[j][k][i-1]][k][i-1])%mod;
}
ll solve(){
    ll l=1,r=1,ret=0,pos=0;
    while(l<=strlen(t+1)){
        r++;
        while(t[r]>='0'&&t[r]<='9')r++;
        if(!cnt[Int(t[l])])return -1;
        if(r-l==1){
            ret=(ret+nxtlen[pos][Int(t[l])][0])%mod;
            pos=nxt[pos][Int(t[l])][0];
        }
        else{
            ll res=0,less=0;
            for(int i=l+1;i<r;i++){
                res=(res*10+(less*10+t[i]-'0')/cnt[Int(t[l])])%mod;
                less=(less*10+t[i]-'0')%cnt[Int(t[l])];
            }
            if(!less)
                res=(res+(mod-1))%mod,less=cnt[Int(t[l])];
            ret=(ret+res*len)%mod;
            ll bit=0;
            while(less){
                if(less&1){
                    ret=(ret+nxtlen[pos][Int(t[l])][bit])%mod;
                    pos=nxt[pos][Int(t[l])][bit];
                }
                bit++,less>>=1;
            }
        }
        l=r;
    }
    return ret;
}
int main(){
    freopen("pre.in","r",stdin);
    freopen("pre.out","w",stdout);
    cin>>s+1>>T;
    len=strlen(s+1);
    init();
    while(T--){
        cin>>t+1;
        cout<<solve()<<'\n';
    }
    return 0;
}

D. 移动

难度:蓝
机房大佬随手贪心成功拿到85pts。(数据真水啊)
考虑用最短路的思想。
首先把能通过闸门的时间段存起来标号(就是离散化啦),然后设 \(dp_i\) 为到达第 \(i\) 个时间段内的最快用时。
将(闸门的标号,时间段的标号,时间)放到一个结构体,然后每次向两边更新新的状态放到优先队列里,输出 \(dp_{id_{n+1}}\) 就行了。
具体看代码。


#include<bits/stdc++.h>
#define ll int
#define pb push_back
#define mp make_pair
#define pll pair<int,int>
#define mxn 200010
using namespace std;
ll n,m,idsum[mxn],dp[mxn];
vector<pll> t[mxn],tmp;
struct node{
    ll id,num,tim;
};
bool operator<(node &x,node &y){
    return x.tim<y.tim;
}
bool operator>(node x,node y){
    return y.tim>x.tim;
}
priority_queue<node,vector<node>,greater<node> > q;
void init(){
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        int a,b,c;
        cin>>a>>b>>c;
        t[a].pb(mp(b,c));
    }
    t[0].pb(mp(0,2e9)),t[n+1].pb(mp(0,2e9));
    idsum[1]=1;
    for(int i=1;i<=n;i++){
        sort(t[i].begin(),t[i].end());
        ll l=-1;
        tmp.clear();
        for(int j=0;j<t[i].size();j++){
            pll v=t[i][j];
            if(v.first>l+1)
                tmp.pb(mp(l+1,v.first-1));
            l=max(l,v.second);
        }
        tmp.pb(mp(l+1,2e9));
        t[i]=tmp;
        idsum[i+1]=idsum[i]+t[i].size();
    }
    memset(dp,0x3f,sizeof(dp));
    return;
}
void qush(node u,int pos){
    if(pos<0||pos>n+1)return;
    ll p=t[u.num][u.id-idsum[u.num]].second;
    ll rnk=lower_bound(t[pos].begin(),t[pos].end(),pair<ll,ll>(u.tim+1,0))-t[pos].begin()-1;
    if(t[pos][rnk].second>=u.tim+1){
        if(dp[idsum[pos]+rnk]>u.tim+1){
            dp[idsum[pos]+rnk]=u.tim+1;
            q.push(node{idsum[pos]+rnk,pos,u.tim+1});
        }
    }
    rnk++;
    while(rnk<t[pos].size()&&t[pos][rnk].first<=p+1){
        if(dp[idsum[pos]+rnk]>t[pos][rnk].first){
            dp[idsum[pos]+rnk]=t[pos][rnk].first;
            q.push(node{idsum[pos]+rnk,pos,t[pos][rnk].first});
        }
        rnk++;
    }
    return;
}
void solve(){
    dp[0]=0;
    q.push(node{0,0,0});
    while(!q.empty()){
        node u=q.top();q.pop();
        if(u.tim>dp[u.id])continue;
        qush(u,u.num+1),qush(u,u.num-1);
    }
}
int main(){
    freopen("move.in","r",stdin);
    freopen("move.out","w",stdout);
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    init();
    solve();
    cout<<dp[idsum[n+1]];
    return 0;
}

标签:rnk,GCD,int,ll,pos,mxn,define,20241023,前缀
From: https://www.cnblogs.com/nagato--yuki/p/18496138

相关文章

  • 每日OJ题_牛客_DP10最大子矩阵_二维前缀和_C++_Java
    目录牛客_DP10最大子矩阵_二维前缀和题目解析C++代码Java代码牛客_DP10最大子矩阵_二维前缀和最大子矩阵_牛客题霸_牛客网(nowcoder.com)描述:        已知矩阵的大小定义为矩阵中所有元素的和。给定一个矩阵,你的任务是找到最大的非空(大小至少是1*1)子矩......
  • 20241023 模拟赛总结
    期望得分:100+100+0+20=220实际得分:100+0+0+0=100(满昏)这算哪门子信心赛……分挂没了,懒得喷。T1人机分类讨论题。T2一眼二分答案,二分最终的最小的最大值,记bi表示把i这个位置加到至少ai需要多少次,然后手玩不知道多少组发现每个位置至少要操作一次,那机器人的启动位置是无......
  • 【算法笔记】前缀和算法原理深度剖析(超全详细版)
    【算法笔记】前缀和算法原理深度剖析(超全详细版)......
  • 隨筆20241023 粘性分区策略及其应用案例
            在大规模数据处理系统中,分区策略的选择对数据的流动性和系统性能至关重要。粘性分区策略(StickyPartitioning)是一种常见的策略,其核心理念是在尽量保持数据顺序的前提下,合理地分配数据到各个分区,以实现负载均衡和提高系统性能。粘性分区策略的工作原理初始数......
  • DictProxy和dict的内存大小_python_如何最小的保存dict_20241023
    缘由:在写多进程的时候,进程之间要用到共享变量,Manager,于是发现了一种新的数据类型:multiprocessing.managers.DictProxy简单来说,这种数据类型特点是,只读模式,内存占用的更少,平均减少了四分之一,最高测试可以减少到1/20,配合pickle.dumps来使用,那么存到本地的文件原本可能是......
  • 20241023
    一、博主咨询沐白情绪主升华为半导体科技重组低空传媒其他沐白情绪主升核心长虹,长虹竞价加强,一致性的加速,当前的长虹定位从趋势核心转变为连板情绪核心,没有先手不太好追高,锚定长虹作为情绪标,去做后排康佳、创维的套利,而明天如果大科技延续分歧,长虹需要接受放量分......
  • 矩阵前缀和
    输入一个n行m列的整数矩阵,再输入q个询问,每个询问包含四个整数x1,y1,x2,y2,表示一个子矩阵的左上角坐标和右下角坐标。对于每个询问输出子矩阵中所有数的和。#include<iostream>usingnamespacestd;intnum[1010][1010],qian[1010][1010];intmain(){intn,m,q;......
  • 【重拾算法第一天】质数&&约数&&欧拉筛 埃氏筛&&GCD
    1.素数素数(PrimeNumber)是指大于1的自然数,只有两个正因数:1和它自身。换句话说,素数是不能被其他自然数整除的数。1.1小素数的判定判定一个数是否为素数,当N≤  时,用试除法,当n>  时,用Miller_Rabin算法根据素数的定义,可以直接得到试除法,用[2,n-1]内的所有数着......
  • 查看不到 ~$ 前缀的文件
    ~$前缀的文件一般都是隐藏文件win10中查看隐藏文件的方式就可以看到再删除但是今天遇到了个看不见的隐藏文件但是打开cmddir/a还是可以看到这个隐藏文件于是使用命令直接删除该文件DEL"file_path\fileName" /A:H  del命令参数说明/F 强制删除文件。/S ......
  • 高维前缀和
    1原来我不会。子集枚举枚举一个集合的每个子集的所有子集。for(ints=0;s<(1<<n);s++){for(ints0=s;;s0=s0&(s0-1)){cout<<s0<<'';}}其中\(s0\)即为枚举的每个子集的所有子集。这是为什么?第一层循环中,我们枚举了一个子集。那么第二层循环中,我们就......