[CSP-S模拟测试97]题解

A.小盆友的游戏

感觉题解解释的很牵强啊……还是打表找规律比较靠谱

对于每个人,它构造了一个期望函数$f(x)$,设它的跟班个数为$cnt[x]$,那么令$f(x)=2^{cnt[x]}-1$(??鬼知道为什么要等于这个)

然后再定义当前局面的期望函数为每个人期望函数之和。

然后你会发现每次猜拳后局面期望函数变化量都是1

那么期望步数其实就是终止局面期望函数值-初始局面期望函数值

$ans=2^{n-1}-1-\sum (2^{cnt[x]}-1)$

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
ll qpow(ll a,ll b)
{
    ll res=1;
    while(b)
    {
        if(b&1)res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return res;
}
int n,a[100005],cnt[100005];
int main()
{
    freopen("game.in","r",stdin);
    freopen("game.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        cnt[a[i]]++;
    }
    ll ans=qpow(2,n-1)-1;ans=(ans+mod)%mod;
    for(int i=1;i<=n;i++)
        ans-=qpow(2,cnt[i])-1,ans=(ans+mod)%mod;
    printf("%lld\n",ans);
    return 0;
}

B.花

垃圾dp。考场上想麻烦了。kuku。

$dp[i][0/1]$表示前i个字符,已经/没有出现过Triple Kill的方案数

转移就行了……

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
int T,n;
ll m,dp[100005][2];
void work()
{
    scanf("%d%lld",&n,&m);
    if(n<3){puts("0");return ;}
    memset(dp,0,sizeof(dp));
    dp[1][0]=m;dp[2][0]=m*m%mod;dp[3][0]=m*m%mod*m%mod;dp[3][0]=(dp[3][0]-m+mod)%mod;dp[3][1]=m;
    for(int i=4;i<=n;i++)
    {
        (dp[i][0]+=dp[i-1][0]*(m-1)%mod)%=mod;
        (dp[i][0]+=dp[i-2][0]*(m-1)%mod)%=mod;
        (dp[i][1]+=dp[i-1][1]*(m-1)%mod)%=mod;
        (dp[i][1]+=dp[i-2][1]*(m-1)%mod)%=mod;
        (dp[i][1]+=dp[i-3][0]*(m-1)%mod)%=mod;
        //cout<<i<<‘ ‘<<dp[i][0]<<‘ ‘<<dp[i][1]<<endl;
    }
    printf("%lld\n",dp[n][1]);
}

int main()
{
    freopen("flower.in","r",stdin);
    freopen("flower.out","w",stdout);
    scanf("%d",&T);
    while(T--)work();
    return 0;
}

C.表格

正解不会。闲的没事自主研发了个指针二维线段树的板子拿了个部分分。

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int base=1001,M=2002,inf=0x3f3f3f3f;
int read()
{
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch==‘-‘)f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-‘0‘,ch=getchar();
    return x*f;
}
int maxx=-inf,minx=inf,maxy=-inf,miny=inf,ans;
int n;
struct node
{
    node *ls,*rs;
    node *ys;
    int v;
    node()
    {
        ls=rs=NULL;
        v=0;
    }
    /*void down()
    {
        if(this->ls!=NULL)this->ls->v=this->v;
        if(this->rs!=NULL)this->rs->v=this->v;
    }*/
};
node *root;
void judge(node *&k)
{
    if(k==NULL)k=new node();
}
void upy(node *&k,int l,int r,int x,int y,int xx,int yy,int val)
{
    if(y<=l&&yy>=r)
    {
        k->v=val;return ;
    }
    int mid=l+r>>1;
    if(y<=mid)
    {
        judge(k->ls);
        upy(k->ls,l,mid,x,y,xx,yy,val);
    }
    if(yy>mid)
    {
        judge(k->rs);
        upy(k->rs,mid+1,r,x,y,xx,yy,val);
    }

}

void upx(node *&k,int l,int r,int x,int y,int xx,int yy,int val)
{
    if(x<=l&&xx>=r)
    {
        judge(k->ys);
        upy(k->ys,1,M,x,y,xx,yy,val);
        return ;
    }
    int mid=l+r>>1;
    if(x<=mid)
    {
        judge(k->ls);
        upx(k->ls,l,mid,x,y,xx,yy,val);
    }
    if(xx>mid)
    {
        judge(k->rs);
        upx(k->rs,mid+1,r,x,y,xx,yy,val);
    }
}
void asky(node *&k,int l,int r,int x,int y)
{
    ans=max(ans,k->v);
    if(l==r)return ;
    int mid=l+r>>1;
    if(y<=mid)
    {
        judge(k->ls);
        asky(k->ls,l,mid,x,y);
    }
    else
    {
        judge(k->rs);
        asky(k->rs,mid+1,r,x,y);
    }
}
void askx(node *&k,int l,int r,int x,int y)
{
    judge(k->ys);
    asky(k->ys,1,M,x,y);
    if(l==r)return ;
    int mid=l+r>>1;
    if(x<=mid)judge(k->ls),askx(k->ls,l,mid,x,y);
    else judge(k->rs),askx(k->rs,mid+1,r,x,y);
}
int vis[100005];
#define F
int main()
{
#ifdef F
    freopen("excel.in","r",stdin);
    freopen("excel.out","w",stdout);
#endif
    n=read();root=new node();
    for(int q=1;q<=n;q++)
    {
        int x=read()+base+1,y=read()+base+1,xx=read()+base,yy=read()+base;
        swap(x,y);swap(xx,yy);
        minx=min(minx,x);maxx=max(maxx,xx);
        miny=min(miny,y);maxy=max(maxy,yy);
        upx(root,1,M,x,y,xx,yy,q);
    }
    int cnt=1;
    for(int i=minx;i<=maxx;i++)
    {
        //puts(" ");
        for(int j=miny;j<=maxy;j++)
        {
            ans=0;askx(root,1,M,i,j);
            if(ans&&!vis[ans])vis[ans]=1,cnt++;
            //cout<<ans<<‘ ‘;
        }
    }

    printf("%d\n",cnt);
    return 0;
}

原文地址:https://www.cnblogs.com/Rorschach-XR/p/11790938.html

时间: 2024-08-30 15:37:31

[CSP-S模拟测试97]题解的相关文章

csp-s模拟测试97

csp-s模拟测试97 猿型毕露.水题一眼秒,火题切不动,还是太菜了. $T1$看了一会儿感觉$woc$期望题$T1??$假的吧??. $T2$秒. $T3$什么玩意儿. 40 01:24:46 100 00:31:38 10 02:49:26 150 02:49:26 $T1$特判错了希望人品可以++. A. 小盆友的游戏 像题解一样构造一个函数那么这个题就是水题了. B. 花 随手$Dp$. C. 表格 $Dee$树帅但是我咕了. 酷(ひど)いよ 酷(ひど)いよ.もういっそ仆(ぼく)の体(か

[CSP-S模拟测试59]题解

以后题解还是单独放吧. A.Divisors 根号筛求所有数的因子,扫一遍去重统计即可. #include<cstdio> #include<iostream> #include<cstring> #include<vector> #include<map> using namespace std; const int N=205; int a[N],m,n; map<int,int> bu; vector<int> re

CSP-S 模拟测试57题解

人生第一次A,B层一块考rank2,虽然说分差没几分,但还是值得纪念. 题解: T1 天空龙: 大神题,因为我从不写快读也没有写考场注释的习惯,所以不会做,全hzoi就kx会做,kx真大神级人物. T2 巨神兵: 大神题,一看数据范围这么小,我们考虑状压,最傻逼的暴力思路是压边,但是这显然不行.正解是压点,设$f[s]$为当前选定点集状态为$s$的方案数. 我们考虑转移,当前选定的点集肯定是可以通过边和没有连过来的点相连构成新的方案.所以转移所以我们考虑枚举补集的子集$k$,设$cnt$为s与k

[CSP-S模拟测试96]题解

以后不能再借没改完题的理由不写题解了…… A.求和 求$\sum \sum i+j-1$ 柿子就不化了吧……这年头pj都不考这么弱智的公式化简了…… 坑点1:模数不定,可能没有2的逆元,那么只要先把乘数里的2去掉就好了. 坑点2:1e18炸long long $\rightarrow$ 慢速乘即可 #include<cstdio> #include<iostream> #include<cstring> #include<vector> using name

[CSP-S模拟测试53]题解

A.u 只涉及到区间修改可以考虑差分,然而如果每一行都差分复杂度还是过高.我们发现差分标记也是连续的(一行横着的一行斜着的),所以可以维护两个 差分的差分,扫两遍统计即可. #include<cstdio> #include<iostream> #include<cstring> using namespace std; typedef long long ll; const int N=2005; int read() { int x=0,f=1;char ch=ge

[CSP-S模拟测试60]题解

回去要补一下命运石之门了…… A.嘟嘟噜 给定报数次数的约瑟夫,递推式为$ans=(ans+m)\% i$. 考虑优化,中间很多次$+m$后是不用取模的,这种情况就可以把加法变乘法了.问题在于如何找到下一次需要取模的位置. 解不等式$ans+km \ge i+k$即可,需要处理一下边界. 据说可以证明复杂度是$O(m \log n)$的,但我不是很会. //考场代码 稍丑 #include<bits/stdc++.h> using namespace std; typedef long lon

[CSP-S模拟测试63]题解

A.Median 这题的数据生成方式并没有什么规律,所以可以认为是随机数据. 维护一个桶,表示当前K长区间里的值域情况. 并且用变量记录中位数值域上的左侧有多少个数,当区间调整时一并调整桶和这个变量即可. 由于是随机数据,所以每次的调整幅度并不会很大,近似于常数. 复杂度$O(n)$. #include<cstdio> #include<iostream> #include<cstring> #include<algorithm> using namespa

CSP-S模拟测试69 题解

一如既往的垃圾,又回到了那个场场垫底的自己,明明考场上都想到正解了,但是就是拿不到分,可能是互奶把rp用光了吧以后一定加强训练代码能力. T1: 考场上一直yy矩阵快速幂,虽然自己矩阵快速幂一点都不会还是硬着头皮yy,发现不可做之后并没有及时转化思路,但其实自己预处理的数组就是正解. 切记:不仅矩阵快速幂是log的,普通快速幂也是2333 然后这题其实很水啊,我们设$dp[i][j]$为前$i$列放$j$个棋子的方案数,然后枚举最后一列放多少个棋子就好了. 转移方程为$dp[i][j]=\sum

[CSP-S模拟测试74]题解

A.梦境 如果不用去重一定要用Multiset……挂30分算是出题人手下留情了. 贪心.把点排序,区间按右端点递增排序.依次考虑每个区间,取能选的最靠左的点即可.multiset维护. #include<cstdio> #include<iostream> #include<cstring> #include<set> #include<algorithm> using namespace std; int read() { int x=0,f=