5.30模拟赛

  5.30了 我...我不知道我究竟该干什么。考试一塌糊涂 我只是不想思考么我想并不是我只是缺乏一些品质罢了吧,只会刷题算什么我要做考试的王者。

今天的失败是下次我的蜕变 ! 我瞧不起那些弱的人。

我的妈妈和爸爸以及姐姐对我很好 我有什么理由再去胆怯。

我的爷爷和奶奶都等着我去上一个好大学,我有什么理由丧失斗志。

我的自己还有很多能力,我有什么理由不去奋斗。

今天是数论专题尽管是这样我也是近乎倒数,我这是怎么回事明明有能力却发现不出题目的性质,原因?用心啊。

首先N==1 时我们很显然的发现了答案应该是5吧。。这个样例使我爆零了,我算服了。

以后注意 想不出来样例就一直想 想不出正解很正常。样例是我和石神探讨下的得出的结论是这样的图:

观察中间的两条边发现我们看成重叠的但是却是有两条这样的边。

首先把中间的边删掉 然后这样的生成树有8种。然后对半删 也就是中间仍有连线 这样方案数是16种 4*4 然后删掉中间的一条边 

知道要说什么了吧 下次我们删掉中间的另外一条边 16 刚好 答案为40.

实话 这道题没有样例解释且题目描述不清晰 生成树不同在此题的定义是指什么我怎么知道?所以我爆零了感觉很不错!不是我不会是这道题出的不好。

我不怪我自己。现在分析一下这道题怎么写 30分好像是可以爆搜的但是及其难写 50分矩阵树定理回去我补一下这个知识点。

100分是找到规律我是这样找规律的利用样例的方法寻找到规律:

1 把中间形成的环这个环全部删掉那么有4n种方案。

2 对于所有的五边形显然我都是要删其中的一条边的 那么此时就是5^n 然后显然的发现必然还会存在一个环那么对于再删一条边即可。

对于一个五边形我们让其再删一条边,那么就是5^(n-1)* 最后一个删去两条边 一条是中间环上的显然!一条是自己边上的显然!

那么方案数是4n 总答案是4n*5^(n-1) 值得一提的是这个和n==2时不冲突 。再值得一提的是这个和1是冲突的想一下5^(n-1)显然有可能出现1中情况所以容斥一下就是-4n

答案如旧。

//#include<bits/stdc++.h>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<queue>
#include<deque>
#include<vector>
#include<utility>
#include<cstdlib>
#include<stack>
#include<cmath>
#include<ctime>
#include<map>
#include<set>
#include<bitset>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)>(y)?(y):(x))
#define INF 10000000000
#define mod 2007
#define ll long long
using namespace std;
char buf[1<<15],*fs,*ft;
inline char getc()
{
    return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
inline int read()
{
    int x=0,f=1;char ch=getc();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
    return x*f;
}
inline void put(int x)
{
    x<0?putchar('-'),x=-x:0;
    int num=0;char ch[50];
    while(x)ch[++num]=x%10+'0',x/=10;
    num==0?putchar('0'):0;
    while(num)putchar(ch[num--]);
    putchar('\n');return;
}
const int MAXN=1010;
int n,T;
ll ans;
//4n*5^(n-1)
inline void fast_pow(ll b,ll p)
{
    ans=1;
    while(p)
    {
        if(p&1)ans=(ans*b)%mod;
        p=p>>1;
        b=(b*b)%mod;
    }
    return;
}
int main()
{
    //freopen("1.in","r",stdin);
    T=read();
    while(T--)
    {
        n=read();
        fast_pow(5,n-1);
        put((4*((n*ans)%mod))%mod);
    }
    return 0;
}
View Code

仔细观察 这题是个dp 发现还比较好写60分观察一下就有了我不知怎么了搞了1h多。

//#include<bits/stdc++.h>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<queue>
#include<deque>
#include<vector>
#include<utility>
#include<cstdlib>
#include<stack>
#include<cmath>
#include<ctime>
#include<map>
#include<set>
#include<bitset>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)>(y)?(y):(x))
#define INF 10000000000
#define mod 998244353
using namespace std;
char buf[1<<15],*fs,*ft;
inline char getc()
{
    return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
inline int read()
{
    int x=0,f=1;char ch=getc();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
    return x*f;
}
inline void put(int x)
{
    x<0?putchar('-'),x=-x:0;
    int num=0;char ch[50];
    while(x)ch[++num]=x%10+'0',x/=10;
    num==0?putchar('0'):0;
    while(num)putchar(ch[num--]);
    putchar('\n');return;
}
const int MAXN=1010;
int n,m,k;
int f[MAXN][MAXN];
//如题 想让我求出一个倒三角的方案数 且多加了一条线。
//讨论 如果 y=x-b 显然是没有卵用的 只有y=x+b才会有点用
//y=x-(n-m); y=x-n+m m-n<0 显然b<0显然 这条线都没用
//y=x+(n-m) 上面还有一条线我的妈呀。。
int main()
{
    //freopen("1.in","r",stdin);
    freopen("path.in","r",stdin);
    freopen("path.out","w",stdout);
    n=read();m=read();
    f[0][0]=1;k=n-m;
    for(int i=0;i<=n;++i)
        for(int j=max(0,i-k);j<=i&&j<=m;++j)
        {
            if(i-1>=0)f[i][j]=(f[i][j]+f[i-1][j])%mod;
            if(j-1>=0)f[i][j]=(f[i][j]+f[i][j-1])%mod;
        }
    /*for(int i=0;i<=n;++i)
    {
        for(int j=0;j<=i&&j<=m;++j)
        {
            cout<<f[i][j]<<' ';
        }
        cout<<endl;
    }*/
    put(f[n][m]);
    return 0;
}
60

100分的话是一个组合数问题 现在还不太会 以后补坑。

dp 写的话 只有60分,眼界放宽点就是一个组合数了,额不会。C(n+m,m)表示从0,0走到n,m的方案数还有一些其他的东西。。

看不懂QAQ。。。

这道题就比较有意思了 我就讨厌这种数数题了,我不会数数。正解是发现这是一个标准的左偏树小根堆。

可以证明的是的确是这样的,不必要去刻意的放上某个数字因为每一个数字都有自己要放的范围,这形成了一个递归的子问题,或者说形成了dp的子状态。

设 f[i] 表示i个数字可以以小根堆左偏树的形式放的方案数,显然的是 f[i]=C(i-1,l)*f[l]*f[r]; l是当前左子树大小 随着i确定而确定。

还是很显然的 就是我们选出一些数字去填左边乘上左右两边的方案数即可。很经典的题目。

这里求子树大小我采用O(n)2次幂直接慢慢求,至于组合数lucas定理即可。

//#include<bits/stdc++.h>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<queue>
#include<deque>
#include<vector>
#include<utility>
#include<cstdlib>
#include<stack>
#include<cmath>
#include<ctime>
#include<map>
#include<set>
#include<bitset>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)>(y)?(y):(x))
#define INF 10000000000
#define mod 998244353
#define ll long long
using namespace std;
char buf[1<<15],*fs,*ft;
inline char getc()
{
    return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
inline int read()
{
    int x=0,f=1;char ch=getc();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
    return x*f;
}
inline void put(int x)
{
    x<0?putchar('-'),x=-x:0;
    int num=0;char ch[50];
    while(x)ch[++num]=x%10+'0',x/=10;
    num==0?putchar('0'):0;
    while(num)putchar(ch[num--]);
    putchar('\n');return;
}
const int MAXN=1000010;
int n,p,s,l,r,res,last,cnt;
ll f[MAXN],fac[MAXN];//f[i]表示i个数字所满足小根堆性质的方案数
//一个看起来非常显然的转移f[i]=f[l]*f[r]*C(i-1,l);
ll inv[MAXN],sz[MAXN];//inverse 相反的 element 要素
inline int fast_pow(ll b,int k)
{
    ll tmp=1;
    while(k)
    {
        if(k&1)tmp=tmp*b%p;
        k=k>>1;
        b=b*b%p;
    }
    return tmp;
}
inline ll lucas(int a,int b)
{
    if(b>a)return 0;
    if(a<p)return (fac[a]*inv[b])%p*inv[a-b]%p;
    return lucas(a/p,b/p)*lucas(a%p,b%p)%p;
}
int main()
{
    //freopen("1.in","r",stdin);
    n=read();p=read();s=min(n,p-1);
    fac[0]=f[0]=f[1]=sz[1]=1;res=2;last=2;
    for(int i=1;i<=s;++i)fac[i]=(fac[i-1]*i)%p;
    inv[s]=fast_pow(fac[s],p-2);
    for(int i=s-1;i>=0;--i)inv[i]=inv[i+1]*(i+1)%p;
    //for(int i=1;i<=s;++i)cout<<inv[i]<<' ';
    for(int i=2;i<=n;++i)
    {
        --res;
        sz[i]=(res<last/2?last/2:last-res)+cnt;
        if(!res)cnt+=last>>1,last=last<<1,res=last;
    }
    //for(int i=2;i<=n;++i)put(sz[i]);
    for(int i=2;i<=n;++i)f[i]=(lucas(i-1,sz[i])*f[sz[i]])%p*f[i-1-sz[i]]%p;
    //for(int i=1;i<=n;++i)cout<<f[i]<<' ';
    put(f[n]);
    return 0;
}
View Code

心态崩了!

posted @ 2019-05-31 19:31  chdy  阅读(187)  评论(0编辑  收藏  举报