首页 > 其他分享 >多校A层冲刺NOIP2024模拟赛03

多校A层冲刺NOIP2024模拟赛03

时间:2024-10-07 19:00:04浏览次数:7  
标签:03 int rep 多校 long using define NOIP2024 mod

多校A层冲刺NOIP2024模拟赛03

还有一个半小时结束才来,题基本没打,全口胡。

T1 五彩斑斓(colorful)

直接统计答案难做,考虑统计四个顶点都一样的。

知道\(n\)行\(m\)列的矩阵有\(\frac{n\times (n+1)\times m\times (m+1)}{4}\)个子矩阵,这个想成选择矩阵的边界就可以证明。

如何统计四个顶点都一样的?

考虑枚举矩阵的上下边界,分别记为\(i,j\),然后扫描每一列,记当前扫描到\(k\)。

如果\(c_{i,k}\ne c_{j,k}\),那么这一列不会作为右边界,舍弃。

如果\(c_{i,k}=c_{j,k}\),那么这一列可以成为右边界或左边界,计数器\(ct_{c_{i,k}}++\),然后\(ans+=ct_{c_{i,k}}\)

清空的时候再扫描一遍列就行了。

时间复杂度\(O(n^2m)\)

点此查看代码
#include<bits/stdc++.h>
#include<bits/extc++.h>
// using namespace __gnu_pbds;
// using namespace __gnu_cxx;
using namespace std;
#define infile(x) freopen(x,"r",stdin)
#define outfile(x) freopen(x,"w",stdout)
#define errfile(x) freopen(x,"w",stderr)
#define rep(i,s,t,p) for(int i = s;i <= t; i += p)
#define drep(i,s,t,p) for(int i = s;i >= t; i -= p)
#ifdef LOCAL
    FILE *InFile = infile("in.in"),*OutFile = outfile("out.out");
    // FILE *ErrFile=errfile("err.err");
#else
    FILE *Infile = infile("colorful.in"),*OutFile = outfile("colorful.out");
    //FILE *ErrFile = stderr;
#endif
using ll=long long;using ull=unsigned long long;
using db = double;using ldb = long double;
const int N = 410,V = 1e6 + 10;
int n,m,a[N][N],ct[V];
inline void solve(){
    cin>>n>>m;
    rep(i,1,n,1)rep(j,1,m,1)cin>>a[i][j];
    ll ans = 0;
    rep(i,1,n,1)rep(j,i,n,1){
        rep(k,1,m,1) if(a[i][k] == a[j][k]){++ct[a[i][k]];ans += ct[a[i][k]];}
        rep(k,1,m,1) if(a[i][k] == a[j][k]) ct[a[i][k]] = 0;
    }
    cout<<1ll*n*(n+1)*m*(m+1)/4-ans;
}
signed main(){
    cin.tie(nullptr)->sync_with_stdio(false);
    cout.tie(nullptr)->sync_with_stdio(false);
    solve();
}

T2 错峰旅行(travel)

答案就是每秒钟时不拥挤的城市个数的乘积,离散化处理一下即可。

点此查看代码
#include<bits/stdc++.h>
#include<bits/extc++.h>
// using namespace __gnu_pbds;
// using namespace __gnu_cxx;
using namespace std;
#define infile(x) freopen(x,"r",stdin)
#define outfile(x) freopen(x,"w",stdout)
#define errfile(x) freopen(x,"w",stderr)
#define rep(i,s,t,p) for(int i = s;i <= t; i += p)
#define drep(i,s,t,p) for(int i = s;i >= t; i -= p)
#ifdef LOCAL
    FILE *InFile = infile("in.in"),*OutFile = outfile("out.out");
    // FILE *ErrFile=errfile("err.err");
#else
    FILE *Infile = infile("travel.in"),*OutFile = outfile("travel.out");
    //FILE *ErrFile = stderr;
#endif
using ll=long long;using ull=unsigned long long;
using db = double;using ldb = long double;
const int N = 5e3 + 10,M = 2e6 + 10,mod = 1e9 + 7;
int s,t,n,m,p[M],ct[N];
struct node{int x,p,d;}a[M];int tot;
inline int power(int a,int b,int mod){
    int res = 1;
    for(;b;a = 1ll*a*a%mod,b>>=1) if(b&1) res = 1ll*res*a%mod;
    return res;
}
inline void solve(){
    cin>>n>>m>>s>>t;
    p[++p[0]] = s;p[++p[0]] = t+1;
    rep(i,1,m,1){
        int x,l,r;cin>>x>>l>>r;r++;
        p[++p[0]] = l;p[++p[0]] = r;
        a[++tot] = {x,l,1};a[++tot] = {x,r,-1};
    }
    m <<= 1;
    sort(a+1,a+1+m,[](node x,node y){return (x.p == y.p?x.d<y.d:x.p<y.p);});
    sort(p+1,p+1+p[0]);p[0] = unique(p+1,p+1+p[0]) - p - 1;
    //cerr<<power(2,100,mod)<<'\n';
    //exit(0);
    ll lsum = 1,nsum = 0,lnum = n,nnum = 0;
    for(int i = 1,j = 0;i < p[0]; ++i){
        nsum = 0,nnum = lnum;
        //cerr<<i<<":  ";
        while(j < m && a[j + 1].p <= p[i]){
            j++;
            int x = a[j].x,d = a[j].d;
            if(ct[x] > 0 && ct[x] + d <= 0) ++nnum;
            else if(ct[x] <= 0 && ct[x] + d > 0) --nnum;
            ct[x] += d;
            //cerr<<j<<' ';
        }
        //cerr<<'\n';
        nsum = lsum*power(nnum,p[i+1]-p[i],mod)%mod;
        lsum = nsum,lnum = nnum;
    }
    cout<<nsum<<'\n';
}
signed main(){
    cin.tie(nullptr)->sync_with_stdio(false);
    cout.tie(nullptr)->sync_with_stdio(false);
    solve();
}

T3 线段树(segment)

区间dp

记\(w_i\)表示包含\(i+0.5\)的区间个数,\(sum_{i,j}\)表示包含\([l,r]\)的区间个数。

\(w\)差分+前缀和解决,考虑如何求\(sum\)

先初始化\(sum_{l,r}\)为恰好为\([l,r]\)的个数,然后有\(sum_{l,r} = sum_{l,r}+sum_{l-1,r}+sum_{l,r+1}-sum_{l-1,r+1}\)

dp方程为\(f_{l,r} = \min\limits_{l\le k<r}f_{l,k}+f_{k+1,r}+w_k-sum_{l,r}\)

答案为\(f_{1,n}+q\)

点此查看代码
#include<bits/stdc++.h>
#include<bits/extc++.h>
// using namespace __gnu_pbds;
// using namespace __gnu_cxx;
using namespace std;
#define infile(x) freopen(x,"r",stdin)
#define outfile(x) freopen(x,"w",stdout)
#define errfile(x) freopen(x,"w",stderr)
using ll=long long;using ull=unsigned long long;
const int N = 510;
ll f[N][N],n,q,sum[N][N],w[N];
signed main(){
    infile("segment.in");outfile("segment.out");
    cin.tie(nullptr)->sync_with_stdio(false);
    cout.tie(nullptr)->sync_with_stdio(false);
    cin>>n>>q;
    for(int i = 1,l,r;i <= q; ++i){
        cin>>l>>r;sum[l][r]++;
        w[l]++,w[r]--;
    }
    for(int i = 1;i <= n; ++i) w[i] += w[i-1];
    for(int len = n - 1;len >= 1; --len){
        for(int l = 1;l + len - 1 <= n; ++l){
            int r = l + len - 1;
            sum[l][r] = sum[l][r] + sum[l-1][r] + sum[l][r+1] - sum[l-1][r+1];
        }
    }
    for(int len = 2;len <= n; ++len){
        for(int l = 1;l + len - 1 <= n; ++l){
            int r = l + len - 1;
            f[l][r] = LLONG_MAX;
            for(int k = l;k < r; ++k){
                f[l][r] = min(f[l][r],f[l][k]+f[k+1][r]+w[k]-sum[l][r]);
            }
        }
    }
    cout<<f[1][n]+q<<'\n';
}

T4 量子隧穿问题(experiment)

计数转概率的trick,就是合法方案 = 合法概率\(\times\)总方案数。

暴力的5pts直接搜索。

发现有\(n\)个顶点\(n\)条边,考虑基环树。

记\(f_{i,j}\)表示狗跑到第\(i\)个盒子\(j\)时有猫的概率。

先考虑一棵树怎么做。对于一条\(u\rightarrow v\)的边,有\(\begin{cases} f_{u,u} &= f_{u-1,u}\times f_{u-1,v}\\ f_{u,v} &= f_{u-1,v}+f_{u-1,u}\times (1-f_{u-1,v}) \end{cases}\)

初始化\(f_{0,i} = [s_i=C]+\frac{[s_i=?]}{2}\)

将基环树环上起点编号最小的一条边删去,然后钦定起点和终点有/无猫,就可以当成一棵树来做。

点此查看代码
#include<bits/stdc++.h>
#include<bits/extc++.h>
// using namespace __gnu_pbds;
// using namespace __gnu_cxx;
using namespace std;
#define infile(x) freopen(x,"r",stdin)
#define outfile(x) freopen(x,"w",stdout)
#define errfile(x) freopen(x,"w",stderr)
#define rep(i,s,t,p) for(int i = s;i <= t; i += p)
#define drep(i,s,t,p) for(int i = s;i >= t; i -= p)
#ifdef LOCAL
    FILE *InFile = infile("in.in"),*OutFile = outfile("out.out");
    // FILE *ErrFile=errfile("err.err");
#else
    FILE *Infile = stdin,*OutFile = stdout;
    //FILE *ErrFile = stderr;
#endif
using ll=long long;using ull=unsigned long long;
using db = double;using ldb = long double;
const int mod = 1e9 + 7,N = 5010,inv2 = 500000004;
struct DSU{
    vector<int> fa;
    DSU(int n) :fa(n+1){iota(fa.begin(),fa.end(),0);}
    inline int find(int x){while(x != fa[x])x = fa[x] = fa[fa[x]];return x;}
    inline bool insame(int x,int y){return find(x) == find(y);}
    inline bool Merge(int x,int y){
        x = find(x),y = find(y);
        if(x == y) return false;else return fa[y] = x,true;
    }
};
int n,to[N],p[N];
char s[N];
inline void solve(){
    cin>>n>>(s+1);rep(i,1,n,1) cin>>to[i];
    DSU f1(n),f2(n); rep(i,1,n,1) f1.Merge(i,to[i]);
    int res;
    drep(i,n,1,1) if(f1.insame(i,n) && !f2.Merge(i,to[i])) res = i;
    int ans = 0;
    for(int l:{0,1})for(int r:{0,1}){
        rep(i,1,n,1) p[i] = 0;
        rep(i,1,n,1){
            if(s[i] == 'C') p[i] = 1;
            if(s[i] == '?') p[i] = inv2;
        }
        int q;
        rep(i,1,n,1){
            if(i == res){
                q = 1ll*(l?p[i]:1-p[i]+mod)*(r?p[to[i]]:1-p[to[i]]+mod)%mod;
                p[i] = l,p[to[i]] = r;
            }
            int x = p[i],y = p[to[i]];
            p[i] = 1ll*x*y%mod;p[to[i]] = (0ll+x+1ll*y*(1-x+mod)%mod)%mod;
        }
        ans = (ans + 1ll*q*p[n]%mod)%mod;
    }
    int tim = 0;rep(i,1,n,1) tim += (s[i] == '?');
    while(tim--)ans = ans*2%mod;
    cout<<ans<<'\n';
}
signed main(){
    cin.tie(nullptr)->sync_with_stdio(false);
    cout.tie(nullptr)->sync_with_stdio(false);
    int T;cin>>T;
    while(T--)solve();
}

标签:03,int,rep,多校,long,using,define,NOIP2024,mod
From: https://www.cnblogs.com/hzoi-Cu/p/18450426

相关文章

  • 多校 A 层冲刺 NOIP2024 模拟赛 03
    多校A层冲刺NOIP2024模拟赛03T1五彩斑斓(colorful)签到题直接暴力枚举是\(O(n^4)\),考虑使用\(bitset\)优化,对每个点开个\(bitset\),预处理它所在一行它及它之前相同颜色的位置,这样就只用枚举另一个点所在列,时间复杂度为\(O(n^3+\frac{n^4}{w})\)。T2错峰旅行(travel)......
  • 网站403forbidden怎么解决
    遇到“403Forbidden”错误通常表示服务器拒绝了请求访问某个资源。解决这个问题可以从以下几个方面入手:1.检查权限设置服务器文件权限:确认服务器上的文件和目录权限是否正确。通常文件权限应为 644,目录权限应为 755。使用命令 chmod 和 chown 调整权限:sudochm......
  • 信息学奥赛复赛复习14-CSP-J2021-03网络连接-字符串处理、数据类型溢出、数据结构Map
    PDF文档公众号回复关键字:202410071P7911[CSP-J2021]网络连接[题目描述]TCP/IP协议是网络通信领域的一项重要协议。今天你的任务,就是尝试利用这个协议,还原一个简化后的网络连接场景。在本问题中,计算机分为两大类:服务机(Server)和客户机(Client)。服务机负责建立连接,客户机......
  • 多校A层冲刺NOIP2024模拟赛02 & csp-s模拟9
    多校A层冲刺NOIP2024模拟赛02四道题因为暑假被拉去当模拟赛暑假集训CSP提高模拟22了,遂直接把赛后代码交了上去,然后就被通知换题了。原\(100+100+100+20\)被在accodersNOI上被卡成了\(100+100+90+10\),更改longlong和int后达到了\(100+100+100+30\)。\(T1\)P318......
  • gym103687D / QOJ3998 The Profiteer
    题意有\(n\)个物品,和一个背包容量上限\(m\)。每个物品有价值\(v_i\)和体积\(a_i\)。你需要选择一段区间\([l,r]\),将这个区间内的体积变为\(b_i\),剩下的不变。然后你对这\(n\)个物品做背包,设背包容量结果为\(f(i)\),需要求出有多少段区间使得\(\dfrac{\sum_{i=1}^mf(......
  • 20241006每日一题洛谷P1031
    对题目第一印象:贪心吧,或者纯模拟第一次贪心,由于左右端堆只能想内一堆移动,遂放弃第一次模拟,开多个数组,(可能还要用递归?),遂放弃于是求助如来佛祖:从逻辑上可以看出,第一堆缺或者多的牌只能移动到第二堆上当第一堆达到期望值时,第一堆便不能再做操作,于是,可以将第二堆作为第一堆来处理......
  • 免费TLS--Let's Encrypt 使用说明
    Let'sEncrypt:这是一个由非营利性组织互联网安全研究小组(ISRG)提供的免费、自动化和开放的证书颁发机构。它为众多网站提供TLS证书,其免费证书的签发/续签可以通过脚本自动化完成。Let'sEncrypt免费证书的有效期通常为90天。官方网站为:https://letsencrypt.org/zh-cn/根据官......
  • NOIP2024集训Day44-45
    \(\textup{反色刷}\)欧拉回路。有解:每个点连接的黑边数为偶数答案个数:连通块数如果一个连通块内有两条路径,则可以在起点之间走两次,则它们一定可以合并成一条。\(\textup{骑士游戏}\)看起来很有让人dp的冲动。假设可以用dp。\(f_u\):消灭\(u\)的最小代价。\[f_u=\m......
  • 2024牛客多校第二场 - I. Red Playing Cards
    思路与官方题解一样,不过我采用了递归的写法,这样就可以避免排序等操作。另外还要注意递归的时候不能让多个不同的递归函数同时修改一个数组,否则这个数组同时被多个函数使用,会很混乱。我这里把它开成了二维来避免这个问题。代码如下:#include<cstdio>#include<algorithm>usingn......
  • STM32F1系列 HAL&LL中文注释库 适用于STM32F101 103 105等MCU 1.8.5版本
    *******下有更多展示图片********由于本汉化不改变官方文件的内容与结构,文档内的链接和官方的营销信息,很多的资源站对内容有检测无法上传,同时考虑这云盘、那博客的限速、会员、账号要求。此文档挂于淘宝,价格:19.9元(GPT回血)说明:机器人自动发货,蓝奏云不限速下载,保证图文......