ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

专项测试(数学1)

2022-01-03 19:33:40  阅读:150  来源: 互联网

标签:专项 ch return int mo 数学 测试 ans mod


今天模拟赛考得没有感觉,感觉数学专题没用到数学......

T1 young

做这个题,本来以为摇摆兵可以早一点切掉,然后让他帮帮我来着

结果他就比我早了一分钟,并且我们两个同时写出了答案相同的错误代码呃呃

好难的亚子

image

该说的题解都说了,我这里给出p的求法

哎呀算了算了直接看代码吧

code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
    int s=0,t=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
    while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();}
    return s*t;
}
const int mod=258280327;
const int N=51;
const int M=9;
int ksm(int x,int y){
    int ret=1;
    while(y){
        if(y&1)ret=ret*x%mod;
        x=x*x%mod;y>>=1;
    }return ret;
}
int n,m,ans;
int f[N][M],g[N][N][M],p[N][N][M][1<<M];
int jc[N],inv[N],pw2[(N+1)*M];
int C(int x,int y){return jc[x]*inv[y]%mod*inv[x-y]%mod;}
int P(int s,int t,int m,int k){
    if(!m)return 1;
    if(!s||!t)return pw2[(s+t)*m];
    if(!k)return pw2[(s+t)*m];
    if(p[s][t][m][k]!=-1)return p[s][t][m][k];
    if((k>>m-1)&1)return p[s][t][m][k]=P(s,t,m-1,k^(1<<(m-1)))*2%mod;
    int ret=0;
    fo(i,0,s)fo(j,0,t){
        int res=C(s,i)*C(t,j)%mod;
        res=res*P(i,j,m-1,k)%mod*P(s-i,t-j,m-1,k)%mod;
        if((i&&j)||(s-i&&t-j))ret=(ret+res)%mod;
    }
    ret=(ret+2*P(s,t,m-1,0))%mod;
    return p[s][t][m][k]=ret;
}
int G(int s,int t,int m){
    if(!s||!t||!m)return 0;
    if(g[s][t][m]!=-1)return g[s][t][m];
    int ret=0;
    fo(k,1,(1<<m)-1)ret=(ret+P(s,t,m,k))%mod;
    return g[s][t][m]=ret;
}
int F(int n,int m){
    if(!m||n<=1)return 0;
    if(f[n][m]!=-1)return f[n][m];
    int ret=0;//cout<<"SB"<<endl;
    fo(i,0,n){
        int res=0;
        if(i)res=(res+pw2[(n-i)*(m-1)]*F(i,m-1))%mod;
        if(n-i)res=(res+pw2[i*(m-1)]*F(n-i,m-1))%mod;
        if(i&&(n-i))res=(res+pw2[(n+1)*(m-1)]+G(i,n-i,m-1))%mod;
        ret=(ret+res*C(n,i))%mod;
    }
    return f[n][m]=ret;
}
signed main(){
    n=read();m=read();
    memset(f,-1,sizeof(f));
    memset(g,-1,sizeof(g));
    memset(p,-1,sizeof(p));
    pw2[0]=1;fo(i,1,(n+1)*m)pw2[i]=pw2[i-1]*2%mod;
    jc[0]=1;fo(i,1,n)jc[i]=jc[i-1]*i%mod;
    inv[0]=1;inv[n]=ksm(jc[n],mod-2);
    fu(i,n-1,1)inv[i]=inv[i+1]*(i+1)%mod;
    ans=F(n,m)*ksm(pw2[n*m],mod-2)%mod;
    // cout<<F(n,m)<<" "<<pw2[n*m]<<endl;
    // cout<<G(2,2,2)<<endl;
    // cout<<P(3,3,3,1)<<endl;
    //1 1 2 1 : 
    // ans=24ll*ksm(16,mod-2)%mod;
    printf("%lld",ans);
}

T2 Simple

设\(f(n)\)为\(n\)位钦定数的个数

答案为\(\sum\limits_{i=1}^{n}i^2f(i)\)

image

这个东西其实是个莫比乌斯反演

我们直接化简它,得到

\[\sum\limits_{d=1}^{n}d*\mu(d)\sum\limits_{i=1}^{\left\lfloor\frac{n}{d} \right\rfloor}i*10^i \]

我们发现后面这个咋也不能杜教筛,但是前面那个却可以,于是调换个顺序

\[\sum\limits_{i=1}^{n}i*10^i\sum\limits_{d=1}^{\left\lfloor\frac{n}{i} \right\rfloor}d*\mu(d) \]

后面这个直接卷上一个\(id\)就能杜教筛了

前面那个有通项公式,直接\(OEIS\)

其实乘一个\(10\)然后两个一消就完事了,被七百信一眼切了,我和摇摆兵玩了一个小时没玩明白

code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
    int s=0,t=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
    while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();}
    return s*t;
}
const int mod=258280327;
const int N=1e7+5;
int ksm(int x,int y){
    int ret=1;
    while(y){
        if(y&1)ret=ret*x%mod;
        x=x*x%mod;y>>=1;
    }return ret;
}
int n,ans;
signed p[N],cnt,R=1e7;
bool vis[N];
int ss[N],iv,i2;
void init(){
    ss[1]=1;
    fo(i,2,R){
        if(!vis[i])p[++cnt]=i,ss[i]=-1;
        for(int j=1;j<=cnt&&i*p[j]<=R;j++){
            vis[i*p[j]]=true;
            if(i%p[j]==0){ss[i*p[j]]=0;break;}
            else ss[i*p[j]]=-ss[i];
        }
    }
    fo(i,1,R)ss[i]=(1ll*ss[i-1]+1ll*i*ss[i]%mod+mod)%mod;
}
int f(int x){return ((9*x-1)%mod*ksm(10,x)%mod+1+mod)%mod*10%mod*iv%mod;}
unordered_map<int,int> mp;
int t(int x){x%=mod;return x*(x+1)%mod*i2%mod;}
int S(int x){
    if(x<=R)return ss[x];
    if(mp.find(x)!=mp.end())return mp[x];
    int ret=1;
    for(int l=2,r;l<=x;l=r+1){
        r=x/(x/l);
        ret=(ret-(t(r)-t(l-1)+mod)*S(x/l)%mod+mod)%mod;
    }return mp[x]=ret;
}
signed main(){
    n=read();init();iv=ksm(81,mod-2);
    i2=ksm(2,mod-2);
    for(int l=1,r;l<=n;l=r+1){
        r=n/(n/l);
        ans=(ans+(f(r)-f(l-1)+mod)*S(n/l))%mod;
    }
    printf("%lld",ans);
    return 0;
}

T3 mate

组合数取模嘛

能直接做的直接做,能\(CRT\)的就\(CRT\),再不济就分解质因数,到点了就输出0

于是乎就切了

正解是线段树维护质因子,因为最后的式子只有一个会变化,所以我们直接用线段树单点修,全局查就行了

code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
    int s=0,t=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
    while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();}
    return s*t;
}
const int N=1e6+5;
int n,mod,xpos,ypos;
int p[N],cnt,R=1e6,buc[N],bmo[N];
bool vis[N];
int mo[N],cmo,an[N],ans;
void init(){
    fo(i,2,R){
        if(!vis[i])p[++cnt]=i;
        for(int j=1;j<=cnt&&i*p[j]<=R;j++){
            vis[i*p[j]]=true;
            if(i%p[j]==0)continue;
        }
    }
}
int jc[15][N],inv[15][N];
int w(int x,int y,int i){return x>=y?jc[i][x]*inv[i][y]%mo[i]*inv[i][x-y]%mo[i]:0;}
int C(int x,int y,int i){if(y==0)return 1;return C(x/mo[i],y/mo[i],i)*w(x%mo[i],y%mo[i],i)%mo[i];}
int ksm(int x,int y,int mod){
    int ret=1;
    while(y){
        if(y&1)ret=ret*x%mod;
        x=x*x%mod;y>>=1;
    }return ret;
}
void spj_init(){
    fo(i,1,cmo){
        int mn=min(n,mo[i]-1);
        jc[i][0]=1;fo(j,1,mn)jc[i][j]=jc[i][j-1]*j%mo[i];
        inv[i][0]=1;inv[i][mn]=ksm(jc[i][mn],mo[i]-2,mo[i]);
        fu(j,mn-1,1)inv[i][j]=inv[i][j+1]*(j+1)%mo[i];
    }
}
void spj1(){
    spj_init();ans=0;
    fo(i,xpos,n-ypos){
        if((i+xpos)&1)continue;
        ans=(ans+C(n,i,1)*C(i,(xpos+i)>>1,1)%mo[1]*C(n-i,(n-i+ypos)>>1,1))%mo[1];
    }
    printf("%lld",ans);
}
int exgcd(int a,int b,int &x,int &y){
    if(!b)return x=1,y=0,a;
    int g=exgcd(b,a%b,x,y),t=x;
    x=y;y=t-a/b*y;return g;
}
void spj2(){
    spj_init();ans=0;
    int sum=1;
    fo(j,1,cmo){
        fo(i,xpos,n-ypos){
            if((i+xpos)&1)continue;
            an[j]=(an[j]+C(n,i,j)*C(i,(xpos+i)>>1,j)%mo[j]*C(n-i,(n-i+ypos)>>1,j))%mo[j];
        }sum*=mo[j];
    }
    fo(i,1,cmo){
        int m=sum/mo[i],x,y;
        exgcd(mo[i],m,x,y);
        ans=(ans+y%sum*m%sum*an[i])%sum;
    }
    ans=(ans+sum)%sum;
    printf("%lld",ans);
}
void CC(int x,int y){
    fo(i,1,cnt){
        if(p[i]>x)break;
        int now=x;
        while(now)buc[i]+=now/p[i],now/=p[i];
    }
    fo(i,1,cnt){
        if(p[i]>y)break;
        int now=y;
        while(now)buc[i]-=now/p[i],now/=p[i];
    }
    fo(i,1,cnt){
        if(p[i]>x-y)break;
        int now=x-y;
        while(now)buc[i]-=now/p[i],now/=p[i];
    }
}
signed main(){
    n=read();mod=read();init();
    xpos=abs(read());ypos=abs(read());
    if(n<xpos+ypos||((n+xpos+ypos)&1)||mod==1){printf("0");return 0;}
    int fl=0,tmp=mod;
    for(int i=1;p[i]*p[i]<=mod;i++){
        if(mod%p[i]==0)mod/=p[i],fl=max(fl,2ll),mo[++cmo]=p[i];
        while(mod%p[i]==0)mod/=p[i],fl=max(fl,3ll);
    }
    if(mod>1)fl=max(fl,1ll),mo[++cmo]=mod;
    if(fl!=1&&n>90000){printf("0");return 0;}
    if(fl==1){spj1();return 0;}
    if(fl==2){spj2();return 0;}
    mod=tmp;
    fo(i,xpos,n-ypos){
        if((xpos+i)&1)continue;
        int res=1;
        CC(n,i);CC(i,(xpos+i)>>1);CC(n-i,(n-i+ypos)>>1);
        fo(i,1,cnt)res=res*ksm(p[i],buc[i],mod)%mod,buc[i]=0;
        ans=(ans+res)%mod;
    }
    printf("%lld",ans);
    return 0;
}

标签:专项,ch,return,int,mo,数学,测试,ans,mod
来源: https://www.cnblogs.com/hzoi-fengwu/p/15760231.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有