NOIP模拟测试17&18

17-T1

给定一个序列,选取其中一个闭区间,使得其中每个元素可以在重新排列后成为一个等比数列的子序列,问区间最长是?

特判比值为1的情况,预处理比值2~1000的幂,存map里。接下来枚举左端点,算出比值,枚举右端点,用平衡树便携判断某个数是否已经在区间内出现过。

#include<bits/stdc++.h>
using namespace std;
inline long long read()
{
long long x=0,fh=1; char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-')fh=-1;ch=getchar();}
while(ch>='0' && ch<='9'){x=(x<<1LL)+(x<<3LL)+(ch^48LL);ch=getchar();}
return x*fh;
}
const int maxn=1e5+5;
const int mod=1e5+3;
const long long INF=1000000000000000000ll;
map<long long,int> fr;
long long a[maxn],mmax,mmin;
int ans=1,h[maxn],tot=1,n;
struct hash{
int num,nxt;
long long val;
}b[maxn<<4];
set<long long> s;
int main(){
for(unsigned long long i=1000;i>=2;i--)
{
for(unsigned long long j=i;j<=INF;j*=i)
{
if(j==0)
break;
fr[(long long)j]=i;
}
}
memset(h,-1,sizeof(h));
n=read();
long long lat=0;
int cnt=0;
for(int i=1;i<=n;i++){
a[i]=read();
if(a[i]==lat)
{
cnt++;
}
else
{
lat=a[i];
cnt=1;
}
ans=max(ans,cnt);
}
for(int l=1;l<n;l++)
{
s.clear();
s.insert(a[l]);
mmax=max(a[l],a[l+1]);
mmin=min(a[l],a[l+1]);
if(mmin==mmax || mmax%mmin)
continue;
s.insert(a[l+1]);
int gys=fr[mmax/mmin];
ans=max(ans,2);
for(int r=l+2;r<=n;r++){
if(s.find(a[r])!=s.end())
break;
s.insert(a[r]);
mmax=max(a[r],a[r-1]);
mmin=min(a[r],a[r-1]);
if(mmax%mmin!=0)
break;
if(fr[mmax/mmin]!=gys)
break;
ans=max(ans,r-l+1);
}
}
printf("%d\n",ans);
return 0;
}

17-T2

对一个节点进行一次”精彩操作”付出的时间代价是这个节点到根节点路径上的轻边数量.

根节点自身进行精彩操作的代价一定是0.我们只关注最坏情况下的时间复杂度,求出每个节点进行一次精彩操作的代价,然后在这些代价中取最大值,就得到了这棵树此时的最坏时间复杂度.

每一个非叶节点将在它的所有儿子中等概率随机选择一个作为重儿子.给出一棵树,按上面的方式随机选择重儿子,求最坏时间复杂度的期望 \(mod1e9+7\)

设 \(f[i][j]\) 为以ii为根节点的子树中最坏时间复杂度小于等于jj的概率设 \(g[i][j]\) 为当前扫到的以ii为父亲节点的所有儿子最坏时间复杂度小于等于 \(j\) 的概率之和.

枚举当前哪一个节点充当重儿子、所有儿子、枚举最坏时间复杂度 \(k\).

如果第二重循环中枚举的儿子恰好是重儿子的话,那么父亲节点的最坏时间复杂度为 \(k\) 的情况可以由两种情况转移过来.

1.重儿子的时间复杂度恰好为 \(k\) 的概率乘上其它儿子时间复杂度小于等于 \(k\) 的概率

2.其它儿子的时间复杂度恰好为 \(k\) 的概率乘上重儿子的时间复杂度小于等于 \(k\) 的概率.


#include<bits/stdc++.h>using namespace std;const int N=5000,M=10000,mod=1e9+7;struct bian{
int nxt,to;}b[M];int head[N],cnt,n,son[N],fa[N],root=1,siz[N];long long ans,f[N][N],g[N],h[N];void add(int from,int to){
b[++cnt].nxt=head[from];
b[cnt].to=to;
head[from]=cnt;}int qp(int a,int b){
int rec=1;
while(b>0)
{
if(b&1)
{
rec=1LL*rec*a%mod;
}
a=1LL*a*a%mod;
b>>=1;
}
return rec;}void dfs(int u){
siz[u]=1;
int i=head[u],v;
while(i)
{
v=b[i].to;
if(v!=fa[u])
{
dfs(v);
siz[u]+=siz[v];
}
i=b[i].nxt;
}
int p=qp(son[u],mod-2);
i=head[u];
while(i)
{
v=b[i].to;
if(v==fa[u])
{
i=b[i].nxt;
continue;
}
for(int j=0;j<=n;j++)
g[j]=1;
int j=head[u],v2;
while(j)
{
v2=b[j].to;
if(v2==fa[u])
{
j=b[j].nxt;
continue;
}
for(int k=0;k<=siz[v2]+1;k++)
{
long long qt=g[k],xz=f[v2][k];
if(k)
{
qt-=g[k-1];
xz-=f[v2][k-1];
}
if(v==v2)
{
h[k]=(qt*f[v2][k]%mod+xz*g[k]%mod-xz*qt%mod+mod)%mod;
}
else
{
xz=f[v2][k-1];
if(k>1)
xz-=f[v2][k-2];
h[k]=(qt*f[v2][k-1]%mod+xz*g[k]%mod-xz*qt%mod+mod)%mod;
}
}
g[0]=h[0],h[0]=0;
for(int k=1;k<=siz[v2]+1;k++)
{
g[k]=(g[k-1]+h[k])%mod;
h[k]=0;
}
j=b[j].nxt;
}
for(int j=siz[u];j>=1;j--)
{
g[j]=(g[j]-g[j-1]+mod)%mod;
}
if(u==1)
{
int xxx;
xxx++;
}
for(int j=0;j<=siz[u];j++){
f[u][j]=(f[u][j]+g[j]*p%mod)%mod;
}
i=b[i].nxt;
}
if(son[u]==0)
f[u][0]=1;
for(int i=1;i<=siz[u]+1;i++)
{
f[u][i]=(f[u][i]+f[u][i-1])%mod;
}}int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&son[i]);
for(int j=1,v;j<=son[i];j++)
{
scanf("%d",&v);
fa[v]=i;
add(i,v);
add(v,i);
}
}
while(fa[root])
root=fa[root];
dfs(root);
for(int i=1;i<=n;i++)
{// cout<<i<<" "<<f[root][i]<<" "<<f[root][i-1]<<endl;
ans=(ans+1LL*i*(f[root][i]-f[root][i-1]+mod)%mod+mod)%mod;
}
printf("%lld\n",ans);
return 0;}

17-T3

在学生的联名提议下,HZ决定在校园内建造一个新型游乐场。

游乐场一共有n个项目,在不同的项目之间有一些走廊相连。

为了保证学生能顺利的游玩完游乐场的每个项目,一个建造方案需要满足以下的条件:将游乐园抽象为一张图,把走廊视为无向边,整张图无重边,无自环。可以通过恰好一次操作使得图中存在一条欧拉回路(从某个点出发经过所有边恰好一次并最终回到起点的路径),其中操作可以是添加一条不在图中的边或是删去一条图中的边。要求操作后的图仍满足条件1,且图中任意两点可以互相到达。设计游乐场布局的任务被委托给了学生会会长小R,小R想先统计出所有的方案,但她数数向来数不清,所以你能不能帮小R统计一下一共有多少种建造方案。

一句话题意:求 \(n\)个点任意连无向边组成的欧拉回路种类乘\(C_{n}^{2}\)

引理

1.无向连通图奇数出度的点个数为偶数.

2.度数均为偶数的无向联通图为欧拉回路.

设:

\(f[i]\) 表示 \(i\) 个点任意连无向边组成的欧拉回路种类.

\(g[i]\) 表示 \(i-1\) 个点任意连无向边组成的图种类.显然有 \(g[i]=2^{C_{i}^{2}}\)

\(i-1\) 个点的无向连通图向 \(i\) 点连成欧拉回路的充要条件是,将原图中奇数出度的点与 \(i\) 点连接。

我们运用容斥,\(f[i]=g[i]-\sum_{j=1}^{i-1}f[j]g[i-j]C_{i-1}^{j-1}\)

(总情况减去不连通的)

#include<bits/stdc++.h>
#define N 5000
using namespace std;
const int mod=1e9+7;
inline int read()
{
int s=0,w=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();}
return s*w;
}
int n;
long long C[N][N],p[N],f[N];
long long qp(long long a,long long b)
{
long long rec=1;
while(b>0)
{
if(b&1)
{
rec*=a;
rec%=mod;
}
a*=a;
a%=mod;
b>>=1;
}
return rec;
}
int main()
{
n=read();
for(int i=0;i<=n;i++)
C[i][0]=1;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=i;j++)
{
C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
}
}
// for(int i=1;i<=n;i++)
// {
// for(int j=1;j<=i;j++)
// {
// printf("%lld ",C[i][j]);
// C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
// }
// puts("");
// }
for(int i=1;i<=n;i++)
p[i]=qp(2,C[i-1][2]);
for(int i=1;i<=n;i++)
{
long long sum=0;
f[i]=p[i];
for(int j=1;j<=i-1;j++)
{
f[i]-=f[j]*p[i-j]%mod*C[i-1][j-1]%mod;
f[i]%=mod;
}
f[i]=((f[i]%mod+mod)%mod+mod)%mod;
}
printf("%lld\n",((f[n]*C[n][2]%mod+mod)%mod+mod)%mod);
return 0;
}
/*
欧拉回路:无向图的每个节点的度数都是偶数度
无向图奇数度的点一定为偶数
n^2递推,f[i]表示i个点的欧拉回路最终图种类数
最终答案为f[n]*C[n][2]
不合法的转移
j个点的欧拉回路
*/

18-T1


#include<bits/stdc++.h>
using namespace std;
const int M=400000,N=200000;
inline int read()
{
    int s=0,w=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
    while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();}
    return s*w;
}
int n,m,cnt,head[N],du[N],zh[N],sumzh;
bool vis[N];
long long ans;
struct bian
{
    int nxt,to;
}b[M];
void add(int from,int to)
{
    b[++cnt].nxt=head[from];
    b[cnt].to=to;
    head[from]=cnt;
}
void dfs(int u,int fa)
{
    vis[u]=1;
    int i=head[u],v;
    while(i)
    {
        v=b[i].to;
        if(!vis[v]&&v!=fa)
        {
            dfs(v,u);
        }
        i=b[i].nxt;
    }
}
int main()
{
    n=read();
    m=read();
    for(int i=1,u,v;i<=m;i++)
    {
        u=read();v=read();
        if(u==v)
        {
            sumzh++;
            zh[u]++;
            continue;
        }
        add(u,v);
        add(v,u);
        du[u]++;
        du[v]++;
    }
    for(int i=1;i<=n;i++)
    {
        if(!vis[i]&&du[i])
        {
            dfs(i,0);
            break;
        }
    }
    bool ok=0;
    for(int i=1;i<=n;i++)
    {
        if(vis[i])
        {
            ok=1;
            break;
        }
    }
    if(ok==0)
        du[1]=1;
    for(int i=1;i<=n;i++)
    {
        if(!vis[i]&&du[i])
        {
            printf("0\n");
            return 0;
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=head[i];j;j=b[j].nxt)
        {
            ans+=du[b[j].to]-1;
        }
    }
    for(int i=1;i<=n;i++)
    {
        ans+=du[i]*sumzh;
    }
    ans+=sumzh*(sumzh-1);
    ans/=2;
    printf("%lld\n",ans);
    return 0;
}
/*
显然起点和重点必须有一条直走一次的边,否则无法走出去
m-2条边允许走2次,把所有边复制一倍,一定欧拉回路
从任何一个点出发,最后回退两条边一定满足目的
答案就是最后推掉的两条边种类
和路上一个自环只走一次的种类*退掉一条边
和路上两个自环只走一次 
非连通图直接白给 
*/ 

18-T2



#include<bits/stdc++.h>
using namespace std;
int n;
long long k,a[1000001],sum,maxn,ans;
int main()
{
    scanf("%d%lld",&n,&k);
    sum=k;
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        sum+=a[i];
        maxn=max(maxn,a[i]);
    }
    maxn+=k;
    long long d=1;
    while(1)
    {
        long long flag=0;
        for(int i=1;i<=n;i++)
        {
            if(a[i]%d!=0)
                flag+=(a[i]/d+1)*d;
            else
                flag+=a[i];
        }
        if(flag<=sum)
            ans=d;
        if(maxn<=d)
            break;
        d=sum/(sum/(d+1));
    }
    cout<<ans<<endl;
    return 0;
}
//https://www.cnblogs.com/wwlwQWQ/p/11408950.html

18-T3



设:

\(f[i][j]\) 为i级的超级树有j条路径且无公共点的方案数

则有:

\[\begin{eqnarray} \\&
f[i+1][j+k]=\sum f[i][j]*f[i][k] \\&
f[i+1][j+k+1]=\sum f[i][j]*f[i][k] \\&
f[i+1][j+k]=\sum f[i][j]*f[i][k]*2*(j+k) \\&
f[i+1][j+k-1]=\sum f[i][j]*f[i][k]*C_{j+k}^{2} \\&
\end{eqnarray}\]

以上四种情况分别对应:

1.左子树和右子树不选根节点本身的路径,再加上原本的方案

2.左子树和右子树,选根节点本身的路径,再加上原本的方案

3.左子树的路径连接根节点,右子树的路径连接根节点

连接根节点有两种方案,即从一条路径的头连或者尾连,即根节点作为七点还是终点。所以要乘二。

4.左子树的路径经过根节点连接右子树的路径


#include<bits/stdc++.h>
using namespace std;
unsigned long long f[400][400],n,mod;
int main()
{
    scanf("%llu%llu",&n,&mod);
    f[1][0]=f[1][1]=1;
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<=(n-i+2);j++)
        {
            for(int k=0;k<=(n-i+2-j);k++)
            {
                f[i+1][j+k]=(f[i+1][j+k]+f[i][j]*f[i][k]%mod)%mod;
                f[i+1][j+k+1]=(f[i+1][j+k+1]+f[i][j]*f[i][k]%mod)%mod;
                f[i+1][j+k]+=f[i][j]*f[i][k]%mod*2%mod*(j+k)%mod;
                f[i+1][j+k]%=mod;
                f[i+1][j+k-1]+=f[i][j]*f[i][k]%mod*(j+k)%mod*(j+k-1)%mod;
                f[i+1][j+k-1]%=mod;
            }
        }
    }
    printf("%llu\n",f[n][1]%mod);
    return 0;
}

NOIP模拟测试17&18的更多相关文章

  1. 8.11 NOIP模拟测试17 入阵曲+将军令+星空

    T1 入阵曲 前缀和维护可以得60分 f[x1][y1][x2][y2]=sum[x2][y2]-sum[x1-1][y2]-sum[x2][y1-1]+sum[x1-1][y1-1];  O(n4) ...

  2. NOIP模拟测试17

    T1:入阵曲 题目大意:给定一个N*M的矩形,问一共有多少个子矩形,使得矩形内所有书的和为k的倍数. 60%:N,M<=80 枚举矩形的左上角和右下角,用二维前缀和求出数字之和. 时间复杂度$O ...

  3. NOIP模拟测试17「入阵曲&#183;将军令&#183;星空」

    入阵曲 题解 应用了一种美妙移项思想, 我们先考虑在一维上的做法 维护前缀和$(sum[r]-sum[l-1])\%k==0$可以转化为 $sum[r]\% k==sum[l-1]\%k$开个桶维护一 ...

  4. 「题解」NOIP模拟测试题解乱写II(36)

    毕竟考得太频繁了于是不可能每次考试都写题解.(我解释个什么劲啊又没有人看) 甚至有的题目都没有改掉.跑过来写题解一方面是总结,另一方面也是放松了. NOIP模拟测试36 T1字符 这题我完全懵逼了.就 ...

  5. 2019.8.3 [HZOI]NOIP模拟测试12 C. 分组

    2019.8.3 [HZOI]NOIP模拟测试12 C. 分组 全场比赛题解:https://pan.baidu.com/s/1eSAMuXk 刚看这题觉得很难,于是数据点分治 k只有1和2两种,分别 ...

  6. 2019.8.3 [HZOI]NOIP模拟测试12 B. 数颜色

    2019.8.3 [HZOI]NOIP模拟测试12 B. 数颜色 全场比赛题解:https://pan.baidu.com/s/1eSAMuXk 数据结构学傻的做法: 对每种颜色开动态开点线段树直接维 ...

  7. 2019.8.3 [HZOI]NOIP模拟测试12 A. 斐波那契(fibonacci)

    2019.8.3 [HZOI]NOIP模拟测试12 A. 斐波那契(fibonacci) 全场比赛题解:https://pan.baidu.com/s/1eSAMuXk 找规律 找两个节点的lca,需 ...

  8. 2019.8.3 NOIP模拟测试12 反思总结【P3938 斐波那契,P3939 数颜色,P3940 分组】

    [题解在下面] 早上5:50,Gekoo同学来到机房并表态:“打暴力,打暴力就对了,打出来我就赢了.” 我:深以为然. (这是个伏笔) 据说hzoi的人还差两次考试[现在是一次了]就要重新分配机房,不 ...

  9. NOIP模拟测试1(2017081501)

    好,今天是cgg第一次举行模拟测试,希望各位支持. 时间限制:2小时 题目链接: 题目一:水得都没名字了 题目二:车站 题目三:选数 不要觉得2小时太少,我的题目很良心,都很简单. 答案可以在模拟测试 ...

随机推荐

  1. SpringBoot自动装配-Import

    1. 简介 @Import导入的类会被Spring加载到IOC容器中.而@Import提供4中用法: 导入Bean 导入配置类 导入 ImportSelector 实现类.一般用于加载配置文件中的类 ...

  2. 【数据结构与算法】字符串匹配(Rabin-Karp 算法和KMP 算法)

    Rabin-Karp 算法 概念 用于在 一个字符串 中查找 另外一个字符串 出现的位置. 与暴力法不同,基本原理就是比较字符串的 哈希码 ( HashCode ) , 快速的确定子字符串是否等于被查 ...

  3. 使用Eclipse下载CRaSH源代码

    Eclipse for Java Developers (Juno)本身有一个eGit组件,通过它可以直接从Git源码库中下载源代码,以下载 CRaSH 为例说明: 从主页上的"Develo ...

  4. filter,interceptor,controllerAdvice,aspect,controller执行顺序

    1.filter,这是java的过滤器,和框架无关的,是所有过滤组件中最外层的,从粒度来说是最大的. 配置方式,有直接实现Filter+@component,@Bean+@configuration( ...

  5. SpringBoot中实现支付宝支付

    本文只介绍当面付(扫码支付)和APP支付 一. 接入准备 #这里分两种情况,正式环境和沙箱环境,本文使用沙箱环境 1.进入支付宝开放平台,创建应用 登录 支付宝开放平台,创建应用并提交审核,审核通过后 ...

  6. SQL 练习6

    查询在 SC 表存在成绩的学生信息 SELECT * from Student WHERE SId in (SELECT SId from SC)

  7. docker运行gerrit(代码审查工具)

    gerrit是什么? Gerrit,一种免费.开放源代码的代码审查软件,使用网页界面. gerrit背景 Gerrit,一种免费.开放源代码的代码审查软件,使用网页界面.利用网页浏览器,同一个团队的软 ...

  8. 多线程同步AutoResetEvent 和ManualResetEvent

  9. C# 简单的对称加密

    const string KEY_64 = "HuidTeac";//注意了,是8个字符 const string IV_64 = "HuidTeac"; pu ...

  10. C#多线程---线程池的工作者线程

    一.线程池简介 创建和销毁线程是一个要耗费大量时间的过程,太多的线程也会浪费内存资源,所以通过Thread类来创建过多的线程反而有损于性能,为了改善这样的问题 ,.net中就引入了线程池. 线程池形象 ...