男人八题2019

打的第三年男人八题了= = 感觉自己可能能创造一个EZ历史上打过最多男人八题的人(嘤嘤嘤我明明是妹子啊

考场上是5题 目前补了7题

 

Biology

模拟= =

//Love and Freedom.
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ll long long
#define inf 20021225
using namespace std;
int read()
{
    int s=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
    return f*s;
}
int main()
{
    int k=read(); int ans=0,n=0;
    while(++n && k)
    {
        ans++; k--; if(!k) break;
        if(n!=1)
            ans+=n, k--;
    }
    printf("%d\n",ans);
    return 0;
}
biology

 

Chemistry

发现最有用的是中间的 它在每一个小矩形都算了 所以它对矩形之间的差是没有贡献的 然后考虑我们把两个矩形补齐 所以就是看最小的和和最大的和然后直接乘一下就可以了

//Love and Freedom.
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ll long long
#define inf 20021225
using namespace std;
int read()
{
    int s=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
    return f*s;
}
int main()
{
    //freopen("chemistry.in","r",stdin);
    //freopen("chemistry.out","w",stdout);
    int n=read(),a=read(),b=read(),c=read(),d=read();
    int s1=a+b,s2=a+c,s3=b+d,s4=c+d;
    int mn=min(s1,min(s2,min(s3,s4))),mx=max(s1,max(s2,max(s3,s4)));
    int k=mx-mn; k=n-k; printf("%I64d\n",1ll*k*n);
    return 0;
}
chemistry

 

Chinese

考虑dp $f[i][j]=\sum_{k=0}^{i-1} f[i-1][j-k]$ 显然前缀和优化 O(nk)

//Love and Freedom.
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ll long long
#define inf 20021225
#define mdn 998244353
#define N 1001
using namespace std;
int read()
{
    int s=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
    return f*s;
}
void upd(int &x,int y){x+=x+y>=mdn?y-mdn:y;}
int f[N],pre[N];
int qry(int l,int r)
{
    if(l<=0)    return pre[r];
    return (mdn+pre[r]-pre[l-1])%mdn;
}
int main()
{
    int n=read(),k=read();
    f[0]=pre[0]=1;
    for(int i=1;i<=n;i++)
    {
        int top=min(1ll*k,1ll*i*(i-1)/2);
        for(int j=1;j<=top;j++)    pre[j]=pre[j-1],upd(pre[j],f[j]);
        for(int j=0;j<=top;j++)    f[j]=qry(j-i+1,j);
    }
    printf("%d\n",f[k]);
    return 0;
}
chinese

 

English

其实之前看过但是考场上死活想不起来怎么做= = 二分答案然后考虑怎么判断 中位数常见套路<x记为0 >=x记为1 然后发现最靠近mid的连续两个0/1就是答案 特判01交替 多的最后会留下来 复杂度O(nlgn)

//Love and Freedom.
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdio>
#define ll long long
#define inf 20021225
#define N 100010
using namespace std;
int read()
{
    int s=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')    f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
    return f*s;
}
int a[N<<1],tmp[N<<1],n;
bool check(int x)
{
    for(int i=1;i<(n<<1);i++)    tmp[i]=a[i]>=x;
    int mid=n;
    for(int d=0;d<n-1;d++)
    {
        if(tmp[mid-d-1]==tmp[mid-d])    return tmp[mid-d];
        if(tmp[mid+d+1]==tmp[mid+d])    return tmp[mid+d];
    }
    return tmp[1];
}
int main()
{
    n=read(); int mx=1;
    for(int i=1;i<(n<<1);i++)    a[i]=read(),mx=max(mx,a[i]);
    int l=1,r=mx,ans=1;
    while(l<=r)
    {
        int mid=l+r>>1;
        if(check(mid))    l=mid+1,ans=mid;
        else    r=mid-1;
    }
    printf("%d\n",ans);
    return 0;
}
english

 

Geography

2017男人八题原题海星 直接反过来做然后线段树/bit维护就行

//Love and Freedom.
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ll long long
#define inf 20021225
#define N 100010
#define lowbit(x) (x&-x)
using namespace std;
int read()
{
    int s=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
    return f*s;
}
struct bit
{
    int a[N],n;
    void add(int x){while(x<=n)    a[x]++,x+=lowbit(x);}
    int qry(int x){int ans=0; while(x)    ans+=a[x],x-=lowbit(x); return ans;}
}t[2];
int cnt;
void modify(int l,int r)
{
    t[0].add(l); t[1].add(r); cnt++;
}
int query(int l,int r)
{
    int ans1=t[0].qry(r); ans1=cnt-ans1;
    int ans2=t[1].qry(l-1);
    return cnt-ans1-ans2;
}
int main()
{
    int n=read(); t[0].n=t[1].n=n;
    while(n--)
    {
        int t=read(),l=read(),r=read();
        if(t==1)    modify(l,r);
        else    printf("%d\n",query(l,r));
    }
    return 0;
}
geography

 

History

考虑直接暴力维护前k小值 然后呢有一个指针指向当前k个里面的最大的记为x 然后选进来一个看它>x的话直接选走 不然的话就选走x把它扔进来 然后发现这玩意是单调的所以它只会减O(n)次 那么我们就做完了

//Love and Freedom.
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ll long long
#define inf 20021225
#define N 100010
using namespace std;
int read()
{
    int s=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
    return f*s;
}
int a[N],buc[N],n,k,p,tmp[N]; ll val[2];
int main()
{
    n=read();
    for(int i=1;i<=n;i++)    a[i]=read();
    sort(tmp+1,tmp+n+1); k=read();
    while(k--)
    {
        p=read(); int k=1,top=0; val[0]=val[1]=0;
        for(int i=1;i<p;i++)    buc[a[i]]++,top=max(top,a[i]);
        for(int i=p;i<=n;i++)
        {
            if(a[i]>top)    val[k]+=a[i], k^=1;
            else
            {
                val[k]+=top; buc[top]--; k^=1; buc[a[i]]++;
                while(!buc[top] && top)    top--;
            }
        }
        for(;top;top--)
            while(buc[top])    val[k]+=top,k^=1,buc[top]--;
        printf("%lld\n",val[1]-val[0]);
    }
    return 0;
}
history

 

Math

留坑

 

Physics

好题ovo 做过弱化版 是正睿17的给 有一个N^2神仙DP方法之前会现在不会了反正对加强版不重要我们就不管了

考虑暴力DP $f[i][j]$表示左走不超过i一共j个叶子 $f[i][j]= [j==1] + \sum_{k=0}^j f[i-1][k] * f[i][j-k]$ 典型的卷积形式 根据常见套路 我们把它写作生成函数形式$F_i(x)$

有$F_i(x)=x+F_i(x)*F_{i-1}(x)$ 所以有$F_i(x)=\frac{x}{1-F_{i-1}(x)}$ 继续根据常见套路 可以把$F_i(x)$写作$\frac{A_i(x)}{B_i(x)}$ 然后我们发现这个式子性质很好 把$F_{i-1}(x)$用这玩意替换一下可以得到递推关系

$A_i(x)=xB_{i-1}(x)$ $B_i(x)=B_{i-1}(x)-A_{i-1}(x)$ 这个玩意显然可以用矩乘优化转移 具体形式懒得写了可以看代码 有边界$A_0(x)=x$,$B_0(x)=1$ 还是常见套路 我们把单位根带进去 然后IDFT一下就可以分别得到A和B接着多项式求逆一下就做完了qwq

代码也不长很好写。

//Love and Freedom.
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ll long long
#define inf 20021225
#define mdn 998244353
#define N 400010
#define G 3
using namespace std;
int read()
{
    int s=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
    return f*s;
}
void upd(int &x,int y){x+=x+y>=mdn?y-mdn:y;}
struct mtx
{
    int a[2][2],n;
    mtx(){memset(a,0,sizeof(a)); n=2;}
    void diag(){memset(a,0,sizeof(a)); for(int i=0;i<n;i++) a[i][i]=1;}
};
mtx operator*(mtx a,mtx b)
{
    mtx tmp=mtx();
    for(int i=0;i<a.n;i++)    for(int j=0;j<a.n;j++)
        for(int k=0;k<a.n;k++)    upd(tmp.a[i][j],1ll*a.a[i][k]*b.a[k][j]%mdn);
    return tmp;
}
mtx mksm(mtx bs,int mi)
{
    mtx ans=mtx(); ans.diag();
    while(mi)
    {
        if(mi&1)    ans=ans*bs;
        bs=bs*bs; mi>>=1;
    }
    return ans;
}
int ksm(int bs,int mi)
{
    int ans=1;
    while(mi)
    {
        if(mi&1)    ans=1ll*ans*bs%mdn;
        bs=1ll*bs*bs%mdn; mi>>=1;
    }
    return ans;
}
int r[N];
int init(int n)
{
    int l=0,lim=1;
    while(lim<n)    lim<<=1,l++;
    for(int i=0;i<lim;i++)
        r[i]=(r[i>>1]>>1)|((i&1)<<l-1);
    return lim;
}
void ntt(int *a,int lim,int f)
{
    for(int i=0;i<lim;i++)    if(r[i]>i)
        swap(a[r[i]],a[i]);
    for(int k=2,mid=1;k<=lim;k<<=1,mid<<=1)
    {
        int Wn=ksm(G,(mdn-1)/k); if(f)    Wn=ksm(Wn,mdn-2);
        for(int w=1,i=0;i<lim;i+=k,w=1)    for(int j=0;j<mid;j++,w=1ll*w*Wn%mdn)
        {
            int x=a[i+j],y=1ll*w*a[i+mid+j]%mdn;
            a[i+j]=(x+y)%mdn; a[i+mid+j]=(mdn+x-y)%mdn;
        }
    }
    if(f)    for(int inv=ksm(lim,mdn-2),i=0;i<lim;i++)
        a[i]=1ll*a[i]*inv%mdn;
}
int tmp[N];
void poly_inv(int *a,int *ans,int n)
{
    if(n==1){ans[0]=ksm(a[0],mdn-2); return;}
    int mid=n+1>>1; poly_inv(a,ans,mid);
    int lim=init(n<<1);
    for(int i=0;i<n;i++)    tmp[i]=a[i];
    for(int i=n;i<lim;i++)    tmp[i]=0;
    ntt(tmp,lim,0); ntt(ans,lim,0);
    for(int i=0;i<lim;i++)
        ans[i]=(2ll-1ll*tmp[i]*ans[i]%mdn+mdn)*ans[i]%mdn;
    ntt(ans,lim,1);
    for(int i=n;i<lim;i++)    ans[i]=0;
}
mtx solve(int w,int n)
{
    mtx k; k.n=2; k.a[0][0]=1; k.a[0][1]=mdn-1; k.a[1][0]=w; k.a[1][1]=0;
    k=mksm(k,n); mtx ans; ans.a[0][0]=(k.a[0][0]+1ll*w*k.a[0][1]%mdn)%mdn;
    ans.a[1][0]=(k.a[1][0]+1ll*w*k.a[1][1]%mdn)%mdn;
    return ans;
}
int a[N],b[N],f[N],ib[N];
int main()
{
    int n=read(),m=read(); int lim; mtx ans;
    lim=init(n+2); int Wn=ksm(G,(mdn-1)/lim);
    for(int i=0,w=1;i<lim;i++,w=1ll*w*Wn%mdn)
        ans=solve(w,n),a[i]=ans.a[1][0],b[i]=ans.a[0][0],printf("%d %d\n",a[i],b[i]);
    ntt(a,lim,1); ntt(b,lim,1); poly_inv(b,ib,m);
    lim=init(m+n+2); ntt(ib,lim,0); ntt(a,lim,0);
    for(int i=0;i<lim;i++)    f[i]=1ll*a[i]*ib[i]%mdn;
    ntt(f,lim,1); for(int i=1;i<=m;i++)    printf("%d\n",f[i]);
    return 0;
}
physics
posted @ 2019-09-05 22:00  寒雨微凝  阅读(791)  评论(1编辑  收藏  举报