首页 > 其他分享 >NOIP模拟<反思>

NOIP模拟<反思>

时间:2023-11-08 22:22:05浏览次数:33  
标签:return NOIP int sum flatd freopen ans 模拟

NOIP2023模拟12联测33

构造

手摸你就会发现 \(ryxyryxyr\),这样会更优,而且从第三行开始会有多余的贡献。

点击查看代码
// ubsan: undefined
// accoders
#include<bits/stdc++.h>
using namespace std;
char s[100];
char ans[100][100];
int main(){
    freopen("ryx.in","r",stdin);
    freopen("ryx.out","w",stdout);
    int n;
    scanf("%d",&n);
    if(n<=20){
        if(n==0){
            cout<<1<<" "<<3<<endl;
            for(int i=1;i<=3;i++){
                cout<<"x";
            }
            return 0;
        }
        int x=n*2,y=3;
        printf("%d %d\n",x,y);
        for(int i=1;i<=n*2;i++){
            if(i%2) printf("ryx\n");
            else printf("xxx\n");
        }
        return 0;
    }
    s[1]='r';
    int tot=1;
    for(int i=1;i<=9;i++){
        s[++tot]='y';s[++tot]='x';
        s[++tot]='y';s[++tot]='r';
    }
    s[++tot]='y';s[++tot]='x';
    if(n<=100){
        int x=40,y=39;
        printf("%d %d\n",x,y);
        for(int i=1;i<=x;i++){
            for(int j=1;j<=y;j++){
                ans[i][j]='x';
            }
        }
        int sum=n;
        for(int i=1;i<=x;i++){
            if(sum<=19){
                i++;
                for(int j=1;j<=tot;j++){
                    if(sum){
                        ans[i][j]=s[j];
                        if(j>=3){
                            if(s[j]!=s[j-1] && s[j-1]!=s[j-2] && s[j]!=s[j-2]) sum--;
                        }    
                    }
                }
                break;
            }
            if(!sum){
                continue;
            }
            if(i%2){
                for(int j=1;j<=tot;j++) ans[i][j]=s[j];
                sum-=19;
            }
            else{
                continue;
            }
        }
        for(int i=1;i<=x;i++){
            for(int j=1;j<=y;j++){
                cout<<ans[i][j];
            }
            cout<<endl;
        }
        return 0;
    }
    int sum=n;
    int x=40,y=40;
    cout<<x<<" "<<y<<endl;
    for(int i=1;i<=x;i++){
        for(int j=1;j<=y;j++){
            ans[i][j]='y';
        }
    }
    for(int i=1;i<=x;i++){
        if(i==1 || i==2){
            for(int j=1;j<=tot;j++) ans[i][j]=s[j]; 
            sum-=19;
            continue;
        }
        if(sum>=(19+38)){
            for(int j=1;j<=tot;j++) ans[i][j]=s[j];
            sum-=(19+38);
            continue;
        }
        else{
            if(sum){
                sum--;
                ans[i][1]=s[1];
            }
            for(int j=2;j<=tot;j++){
                if(j%2==0) ans[i][j]='y';
                else{
                    if(sum>=3){
                        sum-=3;
                        ans[i][j]=s[j];
                    }
                    else{
                        break;
                    }
                }
            }
            break;
        }
    }
    if(sum){
        ans[1][y]=s[1],ans[2][y]=s[2];
        for(int i=3;i<=x;i++){
            if(!sum) break;
            ans[i][y]=s[i];
            if(sum){
                if(s[i]!=s[i-1] && s[i]!=s[i-2] && s[i-1]!=s[i-2]){
                    sum--;
                }
            }    
        }
    }
    for(int i=1;i<=x;i++){
        for(int j=1;j<=y;j++){
            cout<<ans[i][j];
        }
        cout<<endl;
    }
}

游戏

手摸一场了考试样例没摸出来。不太擅长策略题。

从大到小排完序后,同学最优肯定是将概率分配给一个前缀,老师也是,我们可以二分一个 \(mid\) 表示学生能否使得被抓人数 \(\leq mid\)。
此时对于小于 \(mid\) 的 \(a_i\) 不需要考虑,对于大于等于的有 \((1-p)*a_i\) 的期望抓到人数,让 \((1-p)*a_i /leq mid\) 就可以求出下界,将下界加起来,如果大于 1 ,那就不合法,反之成立。

还可以考虑因为选的是一个前缀,且概率和为 1,\(m\) 为选的个数,所以

\[(1-p_i) \times a_i \leq ans \]

\[p_i \geq \frac{a_i-ans}{a_i} \]

\[\sum_{i=1}^{i=m} \frac{a_i-ans}{a_i} =1 \]

化简的到 \(ans=\frac{m-1}{\sum_{i=1}^{i=m} \frac{1}{a_i}}\)

对每个前缀求出 \(ans\) 去 \(\min\) 就可以。

数数

考虑在序列上一个一个加数,使其构成单调递减的序列 \(F\),合法,考虑可以转移到的状态。

首先一开始是一个长度为 \(n\) 的空序列,然后你从小到大加入每一个数,有一些限制,假设你加入的数在 \(F\) 中出现过,且出现区间为 \(L,R\)。那么考虑将这个数 \(x\) 加入到一个空序列上,限制肯定是这个序列长度 \(len = R\),小于 \(R\) 的话,个数不满足,大于 \(k\) 的话,F值就会大于 \(x\)。然后这个空序列会变成两个序列,然后考虑剩下的空序列最长 \(len' == L-1\),因为跟上面一样,考虑只存长度,这样状态数只有不到 \(2.4 \times 10^5\) 个,然后转移。

点击查看代码
#include<bits/stdc++.h>
#define int long long
const int mod=998244353;
using namespace std;
const int N=100;
int f[N],n;
int l[N],r[N];
map<vector<int>,int>mp;
queue<vector<int>> q;
vector<int> s,b;
map<vector<int>,bool> vis;
signed main(){
    freopen("count.in","r",stdin);
    freopen("count.out","w",stdout);
    scanf("%lld",&n);
    for(int i=1;i<=n;i++) l[i]=n+1,r[i]=0;
    for(int i=1;i<=n;i++){
        scanf("%lld",&f[i]);
        l[f[i]]=min(l[f[i]],i),r[f[i]]=max(r[f[i]],i);
    }
    s.push_back(n);
    mp[s]=1;
    q.push(s);
    vis[s]=1;
    while(!q.empty()){
        s=q.front();
        q.pop();
        vis[s]=0;
        int siz=s.size();
        int i=siz;
        int len=0;
        for(int j=0;j<siz;j++) len=max(len,s[j]);
        int sum=0;
        int cnt=0;
        for(int j=0;j<siz;j++){
            if(s[j]==len) sum++;
            if(s[j]==r[i]) cnt++;
        }
        if(l[i]==n+1 || r[i]==0){
            for(int j=0;j<siz;j++){
                if((s[j]<len || sum>1) && s[j]>0){
                    for(int k=1;k<=s[j];k++){
                        b.clear();
                        b=s;
                        b.erase(b.begin()+j);
                        b.push_back(k-1);
                        b.push_back(s[j]-k);
                        sort(b.begin(),b.end());
                        if(!vis[b]){
                            vis[b]=1;
                            q.push(b);
                        }
                        mp[b]=(mp[b]+mp[s])%mod;
                    }    
                }
            }
        }
        else{
            if(len!=r[i]) continue;
            for(int j=0;j<siz;j++){
                for(int k=1;k<=s[j];k++){
                    b.clear();
                    b=s;
                    b.erase(b.begin()+j);
                    b.push_back(k-1);
                    b.push_back(s[j]-k);
                    sort(b.begin(),b.end());
                    if(b[b.size()-1]==l[i]-1){
                        if(!vis[b]){
                            vis[b]=1;
                            q.push(b);
                        }
                        mp[b]=(mp[b]+mp[s])%mod;    
                    }
                }    
            }
        } 
    }
    vector<int> ed;
    ed.clear();
    for(int i=1;i<=n+1;i++){
        ed.push_back(0);
    }
    printf("%lld",mp[ed]);
}

滈葕

首先考虑 \(D,C\),因为这个限制少,所以尽可能选会更优,选之前判一下哪些点不可以选 \(D或C\)。然后选 \(A,B\),这个可以染色,如果边权为 \(1\) 则颜色不同,否则相同,然后判无解。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=5*1e5+10;
const int M=1e5+10;
int head[M],ver[N*2],nex[N*2],edge[N*2],tot=0;
void add(int x,int y,int w){
    ver[++tot]=y,nex[tot]=head[x],head[x]=tot,edge[tot]=w;
}
int flatd[M],flatc[M];
struct asd{
    int x,y,w;
}a[N];
int ans[M],getans=0;
bool vis[N],flat[N];
int dfs1(int x,int f){
    flat[x]=1;
    if(flatc[x]) return flatc[x];
    for(int i=head[x];i;i=nex[i]){
        int y=ver[i];
        if(y==f) continue;
        if(flat[y]){
            if(flatc[y]==1){
                flatc[x]=1;
                return 1;
            }
            continue;
        }
        if(dfs1(y,x)==1){
            flatc[x]=1;
            return 1;
        }
    }
    flatc[x]=2;
    return 0;
}
int dfs2(int x,int f){
    flat[x]=1;
    if(flatd[x]) return flatd[x];
    for(int i=head[x];i;i=nex[i]){
        int y=ver[i];
        if(y==f) continue;
        if(flat[y]){
            if(flatd[y]==1){
                flatd[x]=1;
                return 1;
            }
            continue;
        }
        if(dfs2(y,x)==1){
            flatd[x]=1;
            return 1;
        }
    }
    flatd[x]=2;
    return 0;
}
void dfs(int x,int f){
    for(int i=head[x];i;i=nex[i]){
        int y=ver[i];
        if(y==f) continue;
        if(ans[y]){
            if(edge[i]) if(ans[x]==ans[y]) getans=1;
            if(!edge[i]) if(ans[x]!=ans[y]) getans=1;
            continue;
        }
        if(edge[i]==1){
            if(ans[x]==1) ans[y]=2;
            else ans[y]=1;    
        }
        else{
            ans[y]=ans[x];
        }
        dfs(y,x);
    }
}
int main(){
    freopen("dopetobly.in","r",stdin);
    freopen("dopetobly.out","w",stdout);
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].w);
        if(a[i].w){
            flatd[a[i].x]=1;
            flatc[a[i].y]=1;
        }
    }
    for(int i=1;i<=m;i++){
        if(a[i].w==0){
            vis[a[i].x]=vis[a[i].y]=1;
            add(a[i].x,a[i].y,a[i].w);
        }
    }
    for(int i=1;i<=n;i++){
        if(!flatc[i]){
            dfs1(i,0);
        }
    }
    tot=0;
    memset(head,0,sizeof(head));
    memset(flat,0,sizeof(flat));
    for(int i=1;i<=m;i++){
        if(a[i].w==0){
            add(a[i].y,a[i].x,a[i].w);
        }
    }
    for(int i=1;i<=n;i++){
        if(!flatd[i]){
            dfs2(i,0);
        }
    }
    for(int i=1;i<=n;i++){
        if(flatd[i]==2) ans[i]=4;
        if(flatc[i]==2) ans[i]=3;
    }
    tot=0;
    memset(head,0,sizeof(head));
    for(int i=1;i<=m;i++){
        if(!ans[a[i].x] && !ans[a[i].y]){
            add(a[i].x,a[i].y,a[i].w);
            add(a[i].y,a[i].x,a[i].w);
        }
    }
    for(int i=1;i<=n;i++){
        if(!ans[i]){
            ans[i]=2;
            dfs(i,0);
        }
    }
    if(getans){
        printf("NO");
        return 0;
    }
    if(!getans) printf("YES\n");
    for(int i=1;i<=n;i++){
        if(ans[i]==1) printf("A");
        if(ans[i]==2) printf("B");
        if(ans[i]==3) printf("C");
        if(ans[i]==4) printf("D");
    }
}

NOIP2023模拟13联测34

origen

首先对 \(a_i\) 做前缀异或和,记为 \(s_i\)。

然后原式变为 \(\sum^{n}_{i=0}\sum_{j=i+1}^{n}(s_i \oplus s_j)^2\)

然后考虑第 \(i\) 位加入 \(s_i\),之后的答案为 \(ans^2\),然后 \(ans^2=(2^0 + 2^1 +…+ 2^{25})^2\),也就是将其二进制拆分,然后按位考虑,肯定有两位异或起来都为 \(1\) 的才会产生贡献,贡献类似于 \(2 \times a \times b \times k_i\),\(k_i\) 表示贡献的次数,然后对于两位相等的没有系数 \(2\)。

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=998244353;
const int N=2*1e5+10;
int a[N],s[N];
int f[25][3][25][3];
int ans[N];
signed main(){
    freopen("origen.in","r",stdin);
    freopen("origen.out","w",stdout);
    int n;
    while(scanf("%lld",&n)==1){
        // scanf("%lld",&n);
        for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
        int cnt=0;
        for(int i=1;i<=n;i++){
            s[i]=s[i-1]^a[i];
            for(int j=1;j<=20;j++){
                for(int k=j;k<=20;k++){
                    int t1=((s[i]&(1ll<<(j-1)))>0);
                    int t2=((s[i]&(1ll<<(k-1)))>0);
                    f[j][t1][k][t2]++;
                    if(j==k){
                        ans[i]+=(1ll<<(j-1))*(1ll<<(k-1))%mod*f[j][t1^1][k][t2^1]%mod;
                        ans[i]%=mod;
                        continue;
                    }
                    ans[i]+=2*(1ll<<(j-1))*(1ll<<(k-1))%mod*f[j][t1^1][k][t2^1]%mod;
                    ans[i]%=mod;
                }
            }
            ans[i]+=s[i]*s[i]%mod;
            ans[i]%=mod;
            cnt=(cnt+ans[i])%mod;
        }
        printf("%lld",cnt);
    }
    
}

标签:return,NOIP,int,sum,flatd,freopen,ans,模拟
From: https://www.cnblogs.com/jinjiaqioi/p/17814203.html

相关文章

  • NOIP游记
    Day-9开始记游记咯~弱省弱校没法停课但是申请了走读两周。放学回家(实际上是宾馆)训练今日成果:费马小定理模运算意义下的逆元因为一个地方没有取模(样例还过了)而全线WA顺便学了个快读(((次小生成树代码量巨大(其实也没有Day~时间到了再更......
  • 【2023.11.08】NOIP2023模拟试题-30
    前言数论迎我归,数学送我葬组合数学不容易,又有DP当T3刚爆零,T4又遭殃OI路上怅前望,且行且彷徨T1最大公约数T1应该想一想就会,接下来我们讨论是怎么减去他的复杂度的。题目的关键在于,如果根据给出的\(a\)推出\(\gcd\)的话,就会有\(9\times10^{10}\)条推导关系。而......
  • 2023-11-08 Android studio下载的模拟器存放路径以及如何修改存放路径 ==》默认路径:C:
    模拟器存放默认路径:C:\Users\Administrator\.android\avd如何修改:设置一个系统变量,如图,点击Help==》EditCustomProperties 然后再弹出的文本框里输入你要存放的路径,比如我存在D盘的adv文件夹里面ANDROID_AVD_HOME=D:\\adv 我的as版本:2022.3.1Patch3 写到最后:c盘......
  • 鸿蒙原生应用开发-DevEco Studio超级终端模拟器的使用
    一、了解超级终端模拟器支持的设备情况该特性在DevEcoStudioV2.1Release及更高版本中支持。目前超级终端模拟器支持“Phone+Phone”、“Phone+Tablet”和“Phone+TV”的设备组网方式,开发者可以使用该超级终端模拟器来调测具备跨设备特性的应用/服务,如应用/服务在不同设备间的流......
  • python123——模拟生成微软序列号
    模拟生成微软序列号描述微软产品一般都一个25位的序列号,是用来区分每份微软产品的产品序列号。产品序列号由五组被“-”分隔开,由字母数字混合编制的字符串组成,每组字符串是由五个字符串组成。如:36XJE-86JVF-MTY62-7Q97Q-6BWJ2每个字符是取自于以下24个字母及数字之中的一个:BCE......
  • STL容器vector的模拟实现
    前言vector是C++STL四大组件之一容器的一部分。vector属于容器中的序列式容器,之所以被称之为容器,是因为在有了模板之后,vector在显示实例化时可以按照不同的需求实例化出存储不同类型数据的类,就像是一个容器一样,你放入什么,它就是什么。vector的本质就是一个可以动态增长的数组,是利用......
  • 直接从 Amazon EC2 控制台模拟竞价型实例集中断的情况
    您现在可以直接从 AmazonEC2控制台将随机的 AmazonEC2竞价型实例中断注入您的竞价型实例集。2022年,我们推出了一项功能,让您可以在 AmazonEC2 控制台中使用 AmazonFaultInjectionSimulator(AmazonFIS) 来模拟 AmazonEC2 收回单个 EC2 竞价型实例时的情况。现......
  • 11.7 模拟赛小记
    摘要:三道原,比较之前的难,发挥不好,八点半从机房外面过去的帅哥真的真的真的好帅我一下子无心大模拟赛了一整个惊艳到。A.油田(oil)P3888GDOI2014拯救莫莉斯状压dp,据说爆搜也能过。本蒟蒻不会写剪枝,喜提20pts。状压dp思路:首先\(n*m<=50\),\(m<=n\),则\(n,m<8\),状压去做是......
  • clumsy 0.3 发布,十年前推出的差网络环境模拟工具
    clumsy0.3现已发布,距离v0.1版本已经过去了十年的时间。clumsy能在Windows平台下人工造成不稳定的网络状况,方便你调试应用程序在极端网络状况下的表现。0.3二进制文件与一年半前发布的0.3RC4相同。将滞后时间上限提高到15秒改用zig0.9.0生成二进制文件......
  • NOIP2023模拟13联测34 总结
    NOIP2023模拟13联测34总结目录NOIP2023模拟13联测34总结比赛过程题目A.origen题目大意思路B.competition题目大意思路C.tour题目大意D.abstract题目大意比赛过程看了一下题,感觉就\(T2\)有一点思路。\(T1\)先打一个\(30\)分暴力,感觉要分位考虑,想了大概\(1h\)就跳......