六省联考2017总结

Day1 T1 期末考试

Sol

一开始想的是二分(wtcl),\(check\)的时候发现要求的东西可以均摊\(O(1)\)...,再加上发现了问题没有单调性。所以,可以暴力枚举的题目为什么要二分啊qwq

直接枚举最大的\(b\)值(即出成绩的日子),设它为\(i\),于是花费的代价=学生等待的时间+将大于\(i\)\(b\)值降低到\(i\)的花费。显然,\(i\)越小,学生等待的时间越小,这个代价具有单调性,可以均摊\(O(1)\)求;对于后者,我们用\(lar\)表示\(\Sigma{b_j-i},(b_j> i)\),即多出来的时间,用lit表示\(\Sigma{i-b_j},(b_j\leq i)\),即少的时间,当\(B<A\)时,当然直接全选择\(B\)操作最好,否则就先将\(lit\)这个空出来的坑用\(A\)操作填满,然后剩下的再用\(B\)操作,然后又可以发现\(lar\)\(lit\)也有单调性,也可以均摊\(O(1)\)求,于是整道题就变成了一道\(O(n)\)的模拟题

Code

#include<bits/stdc++.h>
#define N 100005
#define Max(x,y) ((x)>(y)?(x):(y))
#define Min(x,y) ((x)<(y)?(x):(y))
using namespace std;
typedef long long ll;
int n,m,t[N],b[N];
ll A,B,C;
ll ans,x,xx,maxx;//x为当前剩余有怒气的人数maxx为枚举起点 
ll lit,lar;//比i小的时间总量,比i大的时间总量 
ll l,las;//比i小的b个数

template <class T>
void read(T &x)
{
    char c;int sign=1;
    while((c=getchar())>'9'||c<'0') if(c=='-') sign=-1; x=c-48;
    while((c=getchar())>='0'&&c<='9') x=x*10+c-48; x*=sign;
}
void solveC()//C特别大,直接全部降低 
{
    ll minn=t[1];
    lit=lar=0;
    for(int i=1;i<=m;++i)
    {
        if(b[i]>minn) lar+=(b[i]-minn);
        if(b[i]<minn) lit+=(minn-b[i]);
    }
    if(B<=A) ans=lar*B;//直接降低时间不亏 
    else
    {
        if(lar>=lit) ans=lit*A+(lar-lit)*B;
        else ans=lar*A;
    }
    cout<<ans<<endl;
}

int main()
{
    //init
    read(A);read(B);read(C);
    read(n);read(m);
    for(int i=1;i<=n;++i) read(t[i]);
    sort(t+1,t+n+1);
    for(int i=1;i<=m;++i)
    {
        read(b[i]);
        maxx=Max(maxx,b[i]);
    }
    sort(b+1,b+m+1);
    
    //特判 
    if(C==10000000000000000LL)//C==1e16
    {
        solveC();
        return 0;
    }
    
    //solve
    las=0; ans=1000000000000000LL;
    for(int i=1;i<=n;++i) if(t[i]<maxx) {las=i;++x;xx+=C*(maxx-t[i]);};//xx为等待代价 
    for(int i=1;i<=m;++i) if(b[i]<maxx) {++l;lit+=(maxx-b[i]);} 
    for(int i=maxx;i>=1;--i)//最小的时间 
    {
        while(las&&t[las]>=i)//少一个发怒的人 
        {
            --las;
            --x;
        }
        ll nowans=xx;
        //下面计算调整代价
        
        while(l&&b[l]==i) --l;//少一个小于i的时间 
        if(B<=A) nowans+=B*lar;//全选B 
        else
        {
            if(lar>=lit) nowans+=lit*A+(lar-lit)*B;
            else nowans+=lar*A;
        }
        xx-=C*x;//时间少1 
        lit-=l;
        lar+=(m-l);
        ans=Min(ans,nowans);
    }
    cout<<ans<<endl;
    return 0;
}
/*
3 5 4
5 6
1 1 4 7 8
2 3 3 1 8 2
*/

Day1T2 相逢是问候

想到了欧拉定理,但在递归求解时想错了,以为每次都% \(\varphi(mod)\)...于是在此基础上暴力也写挂了直接100->50->30

Sol


Day1T3 组合数问题

这么水的题考场上居然只打了60分暴力。。。

Sol

发现每一项的共性,即\(r≡i*k+r (mod\) \(k)\)

\(f[i][j]\)表示\(\Sigma{C_{i}^{t}},(t\%k=j)\)

有递推式 \(f[i][j]=f[i-1][j]+f[i-1][j-1]\)
由于是模运算,边界要特判。显然要矩阵加速

\(ans=\)\(\begin{bmatrix} 1 & 0 & ... & 0 & 1\\ 1 & 1 & ... & 0 & 0 \\ .. & ... & ... & ... & ... \\ 0 & 0 & ... & 1 & 0 \\ 0 & 0 & ... & 1 & 1 \\ \end{bmatrix} ^{nk}\)\(\begin{bmatrix} 1\\ 0\\ 0\\ 0\\ 0\\ \end{bmatrix}\)

Code

#include<bits/stdc++.h>
#define N 1000005
#define re register
using namespace std;
typedef long long ll;
ll n,k,r;
ll mod;

struct Matrix
{
    int x,y;
    ll a[60][60];
    Matrix(){x=y=0;memset(a,0,sizeof(a));}
    Matrix operator * (const Matrix c)const
    {
        Matrix ret;
        ret.x=x; ret.y=c.y;
        for(re int i=0;i<x;++i)
            for(re int j=0;j<c.y;++j)
                for(re int k=0;k<y;++k)
                    ret.a[i][j]=(ret.a[i][j]+a[i][k]*c.a[k][j]%mod)%mod;
        return ret;
    }
}one,R;

template <class T>
void read(T &x)
{
    char c;int sign=1;
    while((c=getchar())>'9'||c<'0') if(c=='-') sign=-1; x=c-48;
    while((c=getchar())>='0'&&c<='9') x=x*10+c-48; x*=sign;
}

Matrix quickpow(Matrix a,ll b)
{
    Matrix ret;
    ret.x=ret.y=a.x;
    for(int i=0;i<a.x;++i) ret.a[i][i]=1;
    while(b)
    {
        if(b&1) ret=ret*a;
        a=a*a;
        b>>=1;
    }
    return ret;
}
int main()
{
//  freopen("problem.in","r",stdin);
//  freopen("problem.out","w",stdout);
    read(n);read(mod);read(k);read(r);
    R.x=1; R.y=k; R.a[0][0]=1;
    one.x=one.y=k;
    for(int i=0;i<k;++i)
    {
        one.a[i][i]++;
        one.a[(i-1+k)%k][i]++;
    }
    R=R*quickpow(one,n*k);
    cout<<R.a[0][r]<<endl;
    return 0;
}

Day2T1 摧毁“树状图”

不会,待填坑(然而考场上十几分钟就可以骗到36分为什么要花几个小时去打正解呢)

Day2T2 分手是祝愿

开始有点懵逼,快收卷的时候想多拿点分于是就看到了\(k==n\),发现可以水50,结果不小心水了80....实际上的结论很简单但不很容易看出来,说不定用心做一做可以出来(期望恐惧症)

Sol

由于每个开关最多按一次,所以最多n次可以关掉所有灯,然后又发现题目保证了\(k==n\)有50分,这意味着有50分不用期望,只是让我们求一个最佳方案,我们先解决一下这个问题

一个开关只会影响到比它小的其他灯,也就是说,对于最右边的那个亮着的灯来说,关掉它的方法就是直接按它的开关,于是从右向左枚举每一个灯,如果它亮着的就按一次开关,可以求出最佳点击次数\(cnt\)

根据上面的分析,直接输出\(cnt*n! \%mod\)即可获得\(50pts\)(然而强力的数据竟然给了\(80pts\)

发现一个开关对于灯泡状态的影响是其他开关任意组合都凑不出来的,也就是说,使所有灯都关掉的开关按法并不是多种,而是唯一的,即有些开关必须按,其他的开关不能按,于是我们设\(f[i]\)表示当前还有\(i\)个必须按的开关,要将它变成\(i-1\)个必须按的开关需要的期望步数,状态转移方程如下:

\(f[i]=\frac{i}{n}+(f[i]+f[i+1]+\frac{n-i}{n})\)

这个方程的意思是,要么按到了应该按的开关,要么按错了一个开关,之后还要把它按回来

\(ans=cnt,(cnt\leq k)\)

\(ans=f[k+1]+f[k+2]+...f[cnt]+k,(cnt>k)\)

Code

#include<bits/stdc++.h>
#define N 100005
using namespace std;
typedef long long ll;
const ll mod = 100003;
int n,a[N];
ll ans=1,cnt,k,f[N];

template <class T>
void read(T &x)
{
    char c;int sign=1;
    while((c=getchar())>'9'||c<'0') if(c=='-') sign=-1; x=c-48;
    while((c=getchar())>='0'&&c<='9') x=x*10+c-48; x*=sign;
}

ll quickpow(ll a,ll b)
{
    ll ret=1;
    while(b)
    {
        if(b&1) ret=ret*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return ret;
}
int main()
{
//  freopen("trennen.in","r",stdin);
//  freopen("trennen.out","w",stdout);
    read(n);read(k);
    for(int i=1;i<=n;++i) read(a[i]);
    for(int i=1;i<=n;++i) ans=ans*i%mod;
    cnt=0;
    for(int i=n;i>=1;--i)
    {
        if(a[i])//once
        {
            ++cnt;
            for(int j=1;j*j<=i;++j)
            {
                if(i%j==0)
                {
                    a[j]^=1;
                    if(j*j!=i) a[i/j]^=1;
                }
            }
        }
    }
    if(cnt<=k) cout<<ans*cnt%mod<<endl;
    else
    {
        f[n+1]=0;
        for(int i=n;i>=1;--i) f[i]=((n-i)*f[i+1]+n)%mod*quickpow(i,mod-2)%mod;
        for(int i=k+1;i<=cnt;++i) k=(k+f[i])%mod;
        cout<<ans*k%mod<<endl;
    }
    return 0;
}

Day2T3 寿司餐厅

最小割?一建图脑子就乱,连边连了一年

Sol

WTCL,全场都吊打我

转载于:https://www.cnblogs.com/Chtholly/p/11552173.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据引用\[1\],取证2022七省联考的考生将获得中国PostgreSQL分会颁发的《中国PostgreSQL认证考试技术能力证书》和工信部下属中国电子工业标准化协会颁发的《中国电子信息行业专业技术认定证书》两份证书。这两份证书具有较高的认可度和应用价值,可以在招投标、求职、职称晋升、抵税等方面发挥作用。此外,取证学员还可以享受全职业周期、全国覆盖的就业推荐服务。\[1\] 关于直径的计算,根据引用\[2\]和引用\[3\],在树的分裂情况下,最后的直径的长度可能是以下三种情况的最大值: 1. tree1的直径,假设tree1中,原来最长链的一段为root1。 2. tree2的直径,假设tree2中,原来最长链的一段为root2。 3. tree1的某一个点和tree2的某一个点连接的最长链。 在情况3中,最优的连线方式是取tree1直径的一半、tree2直径的一半并连线。如果直径是奇数,则需要向上取整。具体表达为:⌈Max1\[u\]/2⌉ + ⌈Max2\[v\]/2⌉ + 1。\[3\] 综上所述,取证2022七省联考的考生将获得两份证书,并且在计算直径时需要考虑三种情况,其中情况3的最优连线方式是取tree1直径的一半、tree2直径的一半并连线,如果直径是奇数,则需要向上取整。 #### 引用[.reference_title] - *1* [全国联考 | PostgreSQL初、中级认证考试(5.22)通过考生公示](https://blog.csdn.net/weixin_46199817/article/details/117329421)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [『树直径·树形DP』「四校联考」平衡树](https://blog.csdn.net/Ronaldo7_ZYB/article/details/90488429)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值