专项测试(数学3)

今天非常生气,本来要爆摇摆兵50分的结果只爆了20分......

T1 解方程

这就是一个\(exlucas\)的板子

然而当年这个板子是我硬拍过去的...

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=1<<17;
int T,mod,n,n1,n2,m,a[N];
int ans;
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;
}
int p[N],pk[N],cnt;
void init_p(){
    int now=mod;
    for(int i=2;i*i<=now;i++){
        if(now%i==0)p[++cnt]=i,pk[cnt]=1;
        while(now%i==0)pk[cnt]*=i,now/=i;
    }
    if(now>1)p[++cnt]=now,pk[cnt]=now;
}
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;
}
int inv(int a,int b){
    if(!a)return 0;
    int x,y;exgcd(a,b,x,y);
    return (x%b+b)%b;
}
int mul(int n,int p,int pk){
    if(!n)return 1;int ret=1;
    if(n/pk){
        fo(i,2,pk)if(i%p)ret=ret*i%pk;
        ret=ksm(ret,n/pk,pk);
    }
    fo(i,2,n%pk)if(i%p)ret=ret*i%pk;
    return ret*mul(n/p,p,pk)%pk;
}
int exlucas(int x,int y,int p,int pk){;
    int a=mul(x,p,pk),b=mul(y,p,pk),c=mul(x-y,p,pk);
    int buc=0,ret=1,now;
    now=x;while(now)buc+=now/p,now/=p;
    now=y;while(now)buc-=now/p,now/=p;
    now=x-y;while(now)buc-=now/p,now/=p;
    ret=ret*a%pk*inv(b,pk)%pk*inv(c,pk)%pk*ksm(p,buc,pk)%pk;
    return ret*mod/pk%mod*inv(mod/pk,pk)%mod;
}
int C(int x,int y){
    if(x<y)return 0;
    int ret=0;
    fo(i,1,cnt)ret=(ret+exlucas(x,y,p[i],pk[i]))%mod;
    return ret;
}
signed main(){
    T=read();mod=read();init_p();
    while(T--){
        n=read();n1=read();n2=read();m=read()-n;
        fo(i,1,n1+n2)a[i]=read();
        fo(i,n1+1,n1+n2)m-=a[i]-1;
        if(!n||m<0){printf("0\n");continue;}
        ans=0;
        fo(s,0,(1<<n1)-1){
            int now=m,sum=0,tmp;
            fo(i,1,n1)if((s>>i-1)&1)now-=a[i],sum++;
            if(now<0)tmp=0;
            else tmp=C(n+now-1,n-1);
            if(sum&1)ans=(ans-tmp+mod)%mod;
            else ans=(ans+tmp)%mod;
        }
        printf("%lld\n",ans);
    }
    return 0;
}

T2 宇宙序列

找循环节......

也可以倍增......

\(skyh\)的题解吧,写的可明白了

指数上倍增,很妙

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=10007;
const int N=1<<20;
int ksm(int x,int y,int mo){
    int ret=1;  
    while(y){
        if(y&1)ret=ret*x%mo;
        x=x*x%mo;y>>=1;
    }return ret;
}
int n,p,q,ans,an[N];
int a[N],b[N],f[mod+10][55],lim,len;
void xort(int *a,int lim,int bl){
    for(int t=lim>>1,d=1;d<lim;d<<=1,t>>=1)
        for(int i=0;i<lim;i+=(d<<1))
            fo(j,0,d-1){
                int tmp=a[i+j+d];
                a[i+j+d]=(a[i+j]-tmp+mod)*bl%mod;
                a[i+j]=(a[i+j]+tmp)*bl%mod;
            }
}
signed main(){
    // cout<<ksm(2,5003,mod-1)<<endl;
    n=read();p=read();q=read();
    fo(i,0,(1<<n)-1)a[i]=read();
    for(lim=1,len=0;lim<(1<<n+1);lim<<=1,len++);
    xort(a,lim,1);p++;
    fo(i,0,mod-1)f[i][0]=i;
    fo(i,1,30){
        if((1ll<<i)>p)break;
        fo(x,0,mod-1)f[x][i]=(f[x][i-1]+f[ksm(x,ksm(2,1ll<<i-1,mod-1),mod)][i-1])%mod;
    }
    fo(i,0,lim-1){
        int tmp=a[i];
        fu(j,30,0){
            if((p>>j)&1){
                an[i]=(an[i]+f[tmp][j])%mod;
                tmp=ksm(tmp,ksm(2,(1ll<<j),mod-1),mod);
            }
        }
    }
    xort(an,lim,ksm(2,mod-2,mod));
    ans=an[q];
    printf("%lld",ans);
    return 0;
}

T3 exp

概率期望\(DP\)永远是我不可企及的东西......

转移转移定义定义....

code
#include<bits/stdc++.h>
using namespace std;
// #define double long double 
#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=205;
int T,n,u,s[N*2];char ch[N*2];
double ans,f[N*2][N*2],g[N*2][N*2],p[N][N][N];
double ksm(double x,int y){
    double ret=1;
    while(y){
        if(y&1)ret=ret*x;
        x=x*x;y>>=1;
    }return ret;
}
double c[N][N];
double P(int l,int r,int k){
    int lc=s[k-1]-s[l-1],rc=s[r-1]-s[k];
    double lf=1.0*(k-l+1)/(r-l+1),rf=1.0*(r-k)/(r-l+1);
    return c[lc+rc][lc]*ksm(lf,lc)*g[l][k]*ksm(rf,rc)*g[k+1][r]*lf;
}
signed main(){
    T=read();
    fo(i,0,200){
        c[i][0]=c[i][i]=1;
        fo(j,1,i-1)c[i][j]=c[i-1][j-1]+c[i-1][j];
    }
    while(T--){
        scanf("%s",ch+1);n=strlen(ch+1);
        ans=0;fo(i,1,n)if(ch[i]=='.')s[i+n]=s[i]=1;else s[i+n]=s[i]=0;
        fo(i,1,n*2)s[i]+=s[i-1];
        fo(i,1,n*2){
            fo(j,i,i+n-1){
                if(s[j]-s[i-1]==1&&s[j]-s[j-1]==1)g[i][j]=1,f[i][j]=0;
                else g[i][j]=0,f[i][j]=0;
            }
        }
        fo(len,1,n){
            fo(l,1,2*n-len+1){
                int r=l+len-1;if(s[r]-s[r-1]==0)continue;
                if(g[l][r])continue;
                fo(k,l,r-1){
                    if(s[k]-s[k-1]==0)continue;
                    double p=P(l,r,k);
                    g[l][r]+=p;
                    f[l][r]+=p*(f[l][k]+f[k+1][r]+(k-l)/2.0);
                }
                if(g[l][r]==0)continue;
                f[l][r]/=g[l][r];
            }
        }
        fo(i,n,2*n-1)if(s[i]-s[i-1]==1)ans+=g[i-n+1][i]*(f[i-n+1][i]+(n-1)/2.0);
        printf("%.11lf\n",ans);
    }
    return 0;
}
posted @ 2022-01-07 21:08  fengwu2005  阅读(45)  评论(0编辑  收藏  举报