清北学堂2018年1月省选强化班模拟考试2

期望得分:40+80+30=150

实际得分:80+70+0=150

T1

LYK loves string(string)

Time Limit:1000ms   Memory Limit:128MB

题目描述

LYK喜欢字符串,它认为一个长度为n的字符串一定会有n*(n+1)/2个子串,但是这些子串是不一定全部都不同的,也就是说,不相同的子串可能没有那么多个。LYK认为,两个字符串不同当且仅当它们的长度不同或者某一位上的字符不同。LYK想知道,在字符集大小为k的情况下,有多少种长度为n的字符串,且该字符串共有m个不相同的子串。

由于答案可能很大,你只需输出答案对1e9+7取模后的结果即可。

输入格式(string.in)

一行3个数n,m,k。

输出格式(string.out)

    一行,表示方案总数。

输入样例

2 3 3

输出样例

6

样例解释

共有6种可能,分别是ab,ac,ba,bc,ca,cb。

数据范围

对于20%的数据:1<=n,k<=5。

对于40%的数据:1<=n<=5,1<=k<=1000000000。

对于60%的数据:1<=n<=8,1<=k<=1000000000。

对于100%的数据:1<=n<=10,1<=m<=100,1<=k<=1000000000。

Hint

本题非常easy。

k再大也没有用,最多就用n种字符,最后乘个组合数即可

搜索出用i(i<=n)种字符,有m种不同子串的字符串的个数 f[i]

ans= Σ f[i]*C(k,i)

搜索的时候每次只往后扩增一个新字母

即 若当前字母为i,下一个字母的范围为[1,i+1]

设字符集大小为S

这样对于搜出的每种方案 * S的阶乘 即为 用 S 种 字符的答案

判断一个字符串内有多少种不同的字串时,用哈希

#include<cstdio>
#include<algorithm>

using namespace std;

typedef long long LL;

const int mod=1e9+7;

int n,m;

int a[11];
LL has[11],b[11];

int f[11]; 

int inv[11];

LL Pow(LL a,int b)
{
    LL res=1;
    for(;b;a*=a,b>>=1)
        if(b&1) res*=a;
    return res;
}

void dfs(int now,int cnt,int lim)
{
    if(cnt>lim || n-now+1<lim-cnt) return;
    if(now==n+1)
    {
        for(int i=1;i<=n;++i) has[i]=has[i-1]*10+a[i];
        int sum=0;
        for(int len=1;len<=n;++len) 
        {
            for(int i=1;i+len-1<=n;++i) b[i]=has[i+len-1]-has[i-1]*Pow(10,len); 
            sort(b+1,b+n+1-len+1);
            for(int i=1;i+len-1<=n;++i) if(b[i]!=b[i-1]) sum++;
        }
        if(sum==m) f[lim]++;
        return;
    }
    for(int i=1;i<=cnt;++i) a[now]=i,dfs(now+1,cnt,lim);
    a[now]=cnt+1; dfs(now+1,cnt+1,lim);
}

int getC(int x,int y)
{
    int sum=1;
    for(int i=x-y+1;i<=x;++i) sum=1LL*sum*i%mod;
    for(int i=1;i<=y;++i) sum=1LL*sum*inv[i]%mod;
    return sum;
}

int pow(int a,int b)
{
    int res=1;
    for(;b;a=1LL*a*a%mod,b>>=1)
        if(b&1) res=1LL*res*a%mod;
    return res;
}

int main()
{
    freopen("string.in","r",stdin);
    freopen("string.out","w",stdout); 
    int k;
    scanf("%d%d%d",&n,&m,&k);
    int t=min(n,k);
    for(int i=1;i<=t;++i) dfs(1,0,i);
    LL bit=1;
    for(int i=1;i<=t;++i) 
    {
        inv[i]=pow(i,mod-2);
        bit*=i;
        f[i]=f[i]*bit%mod;
    }
    int ans=0;
    for(int i=1;i<=t;++i) ans=(ans+1LL*f[i]*getC(k,i)%mod)%mod;
    printf("%d",ans); 
}
View Code

考场80分找规律代码

#include<cstdio>
#include<iostream>

using namespace std;

const int mod=1e9+7;

typedef long long LL;

int main()
{
    freopen("string.in","r",stdin);
    freopen("string.out","w",stdout);
    int n,m,k;
    scanf("%d%d%d",&n,&m,&k);
    if(m<n || m>n*(n+1)/2)  cout<<0;
    else if(n==m) cout<<k; 
    else if(m==n*(n+1)/2) 
    {
        LL sum=k;
        for(int i=1;i<n;++i) sum=sum*(k-i)%mod;
        cout<<sum;
    }
    else if(n==2)  cout<<(LL)k*(k-1)/2%mod;
    else if(n==3)
    {
        if(m==4) cout<<'0';
        else if(m==5) cout<<(LL)k*(k-1)%mod*3%mod;
    }
    else if(n==4)
    {
        if(m==5 || m==6) cout<<0;
        else if(m==7) cout<<(LL)k*(k-1)%mod*3%mod;
        else if(m==8) cout<<(LL)k*(k-1)%mod*4%mod;
        else if(m==9) cout<<(LL)k*(k-1)%mod*(k-2)%mod*6%mod;
    }
    else if(n==5)
    {
        if(m<=8) cout<<0;
        else if(m==9) cout<<(LL)k*(k-1)%mod*3%mod;
        else if(m==10) cout<<0;
        else if(m==11) cout<<(LL)k*(k-1)%mod*10%mod;
        else if(m==12) cout<<(LL)k*(k-1)%mod*2%mod*((k-2)*3%mod+1)%mod;
        else if(m==13) cout<<(LL)k*(k-1)%mod*(k-2)%mod*19%mod;
        else if(m==14) cout<<(LL)k*(k-1)%mod*(k-2)%mod*(k-3)%mod*10%mod;
    }
    else if(n==6)
    {
        if(m<=10) cout<<0;
        else if(m==11) cout<<(LL)k*(k-1)%mod*3%mod;
        else if(m==12 || m==13) cout<<0;
        else if(m==14) cout<<(LL)k*(k-1)%mod*10%mod;
        else if(m==15) cout<<(LL)k*(k-1)%mod*3%mod*(2*k-1)%mod;
        else if(m==16) cout<<(LL)k*(k-1)%mod*9%mod;
        else if(m==17) cout<<(LL)k*(k-1)%mod*(k-2)%mod*45%mod;
        else if(m==18) cout<<(LL)k*(k-1)%mod*(k-2)%mod*((k-1)*10%mod+19)%mod;
        else if(m==19) cout<<(LL)k*(k-1)%mod*(k-2)%mod*(k-3)%mod*55%mod;
        else if(m==20) cout<<(LL)k*(k-1)%mod*(k-2)%mod*(k-3)%mod*(k-4)%mod*15%mod;
    }
    else if(n==7)
    {
        if(m!=27) cout<<0;
        else cout<<(LL)k*(k-1)%mod*(k-2)%mod*(k-3)%mod*(k-4)%mod*(k-5)%mod*21%mod;
    }
    else if(n==8)
    {
        if(m!=35) cout<<0;
        else cout<<(LL)k*(k-1)%mod*(k-2)%mod*(k-3)%mod*(k-4)%mod*(k-5)%mod*(k-6)%mod*28%mod;
    }
    else if(n==9)
    {
        if(m!=44) cout<<0;
        else cout<<(LL)k*(k-1)%mod*(k-2)%mod*(k-3)%mod*(k-4)%mod*(k-5)%mod*(k-6)%mod*(k-7)%mod*36%mod;
    }
    else if(n==10)
    {
        if(m!=54) cout<<0;
        else cout<<(LL)k*(k-1)%mod*(k-2)%mod*(k-3)%mod*(k-4)%mod*(k-5)%mod*(k-6)%mod*(k-7)%mod*(k-8)%mod*45%mod;
    }
}
View Code

T2

LYK loves graph(graph)

Time Limit:2000ms   Memory Limit:128MB

题目描述

LYK喜欢花花绿绿的图片,有一天它得到了一张彩色图片,这张图片可以看做是一张n*m的网格图,每个格子都有一种颜色去染着,我们用-1至n*m-1来表示一个格子的颜色。特别地,-1代表这个颜色是黑色,LYK不喜欢黑色!

LYK想将剪下这张图片中的一张子图片来(四联通块),使得这个子图片不存在黑色的格子,并且至少有k个不同的颜色。

但是每个格子有自己的脾气,特别的,第i行第j列这个格子如果被LYK选中了,LYK需要花费相应的代价。LYK想花费尽可能少的代价来剪下一张满足自己要求的图片。

输入格式(graph.in)

    第一行三个整数,n,m,k.

    接下来n行,每行m个数,表示图片中每个格子的颜色,每个数在-1到n*m-1之间。

  接下来n行,每行m个数,表示选择每个位置所需要的代价。

输出格式(graph.out)

一行,表示最小代价和。

输入样例

3 3 3

0 0 1

2 3 3

-1 2 1

3 1 5

4 10 1

9 3 4

输出样例

7

数据范围

对于20%的数据:1<=n,m,k<=4。

对于另外30%的数据:不同的颜色数<=10(不包括-1)。

对于再另外30%的数据:1<=n<=2,1<=m<=15。

对于100%的数据:1<=n,m<=15,1<=k<=7,1<=ai,j<=100000。

数据保证一定有解。

听到标算的我一口老血喷了出来。。。

首先这题肯定是斯坦纳树(除非你想写插头DP)

但是颜色总数高达225种,没法状态压缩

但是询问只要求有7种颜色,所以就可以大开脑洞:

把225种颜色随机映射成7种颜色,然后做斯坦纳树!!!

我们来分析分析它的正确率:

首先可以肯定的是我们算出的答案只会大于等于最优解

因为原本不同的颜色可能被随机映射为相同的颜色,原本相同的颜色随机映射后一定不同

对于最优解中的7种颜色来说,

每种颜色都有7种映射方案,所以一共有7^7种映射方案

而只有这7种颜色映射玩之后还是7种颜色,才有可能算出最优解,这种情况一共有 7! 种

所以随机映射做斯坦纳树一次 的 正确率 为 7!/  7^7  ≈ 0.006 = 0.6% 

错误率=99.4%

那么如果随机映射做斯坦纳树T次,错误率就是 99.6%  ^ T 

如果T=400,错误率 ≈ 9%

那么正确率  = 91%

你还可以再多做几遍,正确率还是蛮高的。。。。。。

#include<queue>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream> 
#include<algorithm>

using namespace std;

#define N 16 

int n,m,k;
int col[N][N],val[N][N];

int a[N*N],mp[N*N];

int ncol[N][N];

int dp[N][N][1<<7];

struct node
{
    int x,y;
    node(int x=0,int y=0):x(x),y(y) {}
};
queue<node>q;

bool vis[N][N];

int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};

int ans=2e9;

void read(int &x)
{
    x=0; int f=1; char c=getchar();
    while(!isdigit(c)) { if(c=='-') f=-1; c=getchar(); } 
    while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
    x*=f;
}

void spfa(int s)
{
    node now;
    int sx,sy,nx,ny;
    while(!q.empty())
    {
        now=q.front();
        q.pop();
        sx=now.x; sy=now.y;
        vis[sx][sy]=false;
        for(int i=0;i<4;++i)
        {
            nx=sx+dx[i]; ny=sy+dy[i];
            if(nx<=0 || nx>n || ny<=0 || ny>m || ncol[nx][ny]==-1) continue;
            if(dp[nx][ny][s]>dp[sx][sy][s]+val[nx][ny]) 
            {
                dp[nx][ny][s]=dp[sx][sy][s]+val[nx][ny];
                if(!vis[nx][ny]) q.push(node(nx,ny)),vis[nx][ny]=true;
            }
        }
    }
}

void Steiner()
{
    memset(dp,63,sizeof(dp));
    int oo=dp[0][0][0];
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j) 
            if(ncol[i][j]!=-1) dp[i][j][1<<ncol[i][j]]=val[i][j];
    int S=1<<k;
    for(int s=1;s<S;++s)
    { 
        for(int i=1;i<=n;++i)
            for(int j=1;j<=m;++j)
            {
                for(int t=(s-1)&s;t;t=(t-1)&s)
                    dp[i][j][s]=min(dp[i][j][s],dp[i][j][t]+dp[i][j][s^t]-val[i][j]);
                if(dp[i][j][s]<oo) q.push(node(i,j)),vis[i][j]=true;
            }
        spfa(s);
    }
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j) ans=min(ans,dp[i][j][S-1]); 
}

int main()
{
    freopen("graph.in","r",stdin);
    freopen("graph.out","w",stdout);
    srand(1000); 
    int tot=0;
    read(n); read(m); read(k);
    for(int i=1;i<=n;++i) 
        for(int j=1;j<=m;++j)  read(col[i][j]),tot=max(tot,col[i][j]);
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j) read(val[i][j]);
    int T=300;
    tot++;
    for(int i=0;i<tot;++i) a[i]=i;
    while(T--)
    {
        random_shuffle(a,a+tot);
        for(int i=0;i<k;++i) mp[a[i]]=i;
        for(int i=k;i<tot;++i) mp[a[i]]=rand()%k;
        for(int i=1;i<=n;++i)
            for(int j=1;j<=m;++j)
                if(col[i][j]==-1) ncol[i][j]=-1; else ncol[i][j]=mp[col[i][j]];
        Steiner();
    } 
    printf("%d",ans);
}
View Code

期望80实际70暴力

说好的不包括-1呢。。。

不过没判-1拿了30里面的20,这数据准是随机的。。。

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>

using namespace std;

#define N 16

int n,m,k;
int col[16][16],val[16][16];

bool tag;
int num,first[N*N];

int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};

void read(int &x)
{
    x=0; int f=1; char c=getchar();
    while(!isdigit(c)) { if(c=='-') f=-1; c=getchar(); }
    while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
    x*=f;
}

void init()
{
    read(n); read(m); read(k);
    memset(first,-1,sizeof(first));
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j)
        {
            read(col[i][j]);
            if(col[i][j]==-1) tag=true;
            else if(first[col[i][j]]==-1) first[col[i][j]]=num++;
        }
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j)
            read(val[i][j]);
}

bool inmap(int x,int y)
{
    if(!x || !y || x>n || y>m) return false;
    return true;
}

bool ok(int s)
{
    int cnt=0;
    for(int i=1,bit=1;i<=30;++i,bit<<=1) cnt+=bool(s&bit);
    return cnt>=k;
}

namespace force1
{
    bool use[5][5];
    bool vis[5][5];
    
    int sum,ans;
    
    bool use_col[N*N];
    
    void dfs2(int x,int y)
    {
        sum++;
        vis[x][y]=true;
        int nx,ny;
        for(int i=0;i<4;++i)
        {
            nx=x+dx[i]; ny=y+dy[i];
            if(inmap(nx,ny) && !vis[nx][ny] && use[nx][ny]) dfs2(nx,ny);
        }
    }
    
    bool connect()
    {
        int sx=0,sy=0,tot=0;
        for(int i=1;i<=n;++i)
            for(int j=1;j<=m;++j)
                if(use[i][j])
                {
                    tot++;
                    if(!sx) sx=i,sy=j;
                }
        sum=0;
        memset(vis,false,sizeof(vis));
        dfs2(sx,sy);
        return sum==tot;
    }
    
    void judge()
    {
        if(!connect()) return;
        int cnt=0,ccnt=0;
        memset(use_col,0,sizeof(use_col));
        for(int i=1;i<=n;++i)
            for(int j=1;j<=m;++j)
                if(use[i][j]) 
                {
                    if(col[i][j]==-1) return;
                    cnt+=val[i][j];
                    if(!use_col[col[i][j]])
                    {
                        use_col[col[i][j]]=true;
                        ccnt++;
                    }
                }
        if(ccnt<k) return;
        ans=min(ans,cnt);
    }
    
    void dfs(int x,int y)
    {
        if(y==m+1)
        {
            if(x==n) 
            {
                judge();
                return;
            }
            dfs(x+1,1);
            return;
        }
        dfs(x,y+1);
        use[x][y]=true;
        dfs(x,y+1);
        use[x][y]=false;
    }
    
    void work()
    {
        ans=2e9;
        dfs(1,1);
        cout<<ans;
    }
}

namespace force2
{
    int ans;
    
    void dfs(int now,int endd,int type,int color,int cost)
    {
        if(now==endd+1)
        {
             if(ok(color)) ans=min(ans,cost);
            return;
        }
        int ncolor,ncost;
        if(col[1][now]!=-1 && col[2][now]!=-1) 
        {
            ncolor=color|(1<<col[1][now])|(1<<col[2][now]);
            ncost=cost+val[1][now]+val[2][now];
            dfs(now+1,endd,0,ncolor,ncost);
        }
        if((!type || type==1) && col[1][now]!=-1)
        {
            ncolor=color|(1<<col[1][now]);
            ncost=cost+val[1][now];
            dfs(now+1,endd,1,ncolor,ncost);
        }
        if((!type || type==2) && col[2][now]!=-1)
        {
            ncolor=color|(1<<col[2][now]);
            ncost=cost+val[2][now];
            dfs(now+1,endd,2,ncolor,ncost);
        }
    }
    
    void work()
    {
        ans=2e9;
        for(int i=1;i<=m;++i)
            for(int j=i;j<=m;++j)
                dfs(i,j,0,0,0);
        cout<<ans;
    }
}

namespace force3
{
    int f[N][N][1024];

    struct node
    {
        int x,y;        
        node(int x_=0,int y_=0) : x(x_),y(y_) { }
    };
    
    queue<node>q;
    
    bool vis[N][N];
    
    void spfa(int s)
    {
        node now;
        int nx,ny;
        while(!q.empty())
        {
            now=q.front();
            q.pop();
            vis[now.x][now.y]=false;
            for(int i=0;i<4;++i)
            {
                nx=now.x+dx[i];
                ny=now.y+dy[i];
                if(!inmap(nx,ny)) continue;
                if(f[now.x][now.y][s]+val[nx][ny]<f[nx][ny][s])
                {
                    f[nx][ny][s]=f[now.x][now.y][s]+val[nx][ny];
                    if(!vis[nx][ny]) q.push(node(nx,ny)),vis[nx][ny]=true;
                }
            }
        }
    }
    
    void work()
    {
        for(int i=1;i<=n;++i)
            for(int j=1;j<=m;++j)
                col[i][j]=first[col[i][j]];
        memset(f,63,sizeof(f));
        for(int i=1;i<=n;++i)
            for(int j=1;j<=m;++j)
                f[i][j][1<<col[i][j]]=val[i][j];
        int S=1<<num; int oo=f[0][0][0];
        for(int s=1;s<S;++s)
        {
            for(int i=1;i<=n;++i)
                for(int j=1;j<=m;++j)
                {
                    for(int t=s-1;t;t=(t-1)&s)
                        f[i][j][s]=min(f[i][j][s],f[i][j][t]+f[i][j][s^t]-val[i][j]);
                    if(f[i][j][s]<oo) q.push(node(i,j)),vis[i][j]=true;
                }
            spfa(s);
        }
        int ans=2e9;
        for(int s=1;s<S;++s)
            if(ok(s))
            {
                for(int i=1;i<=n;++i)
                    for(int j=1;j<=m;++j)
                        ans=min(ans,f[i][j][s]);
            }
        cout<<ans;
    }
}

int main()
{
    freopen("graph.in","r",stdin);
    freopen("graph.out","w",stdout);
    init();
    if(n<=4 && m<=4 && k<=4) force1::work();
    else if(n<=2 && m<=15) force2::work();
    else force3::work();
}
View Code

T3

LYK loves rabbits(rabbits)

Time limit:1000ms     Memory limit:128MB

题目描述

LYK喜欢兔子,它在家中养了3只兔子。

有一天,兔子不堪寂寞玩起了游戏,3只兔子排成一排,分别站在a,b,c这3个位置。

游戏的规则是这样的,重复以下步骤k次:选择两个不同的兔子A和B,假如它们位于X与Y,A可以从X跳到Y+Y-X处,但是跳跃时是不允许一下子跳过两只兔子的,也就是说第三只兔子不在[min{X,Y+Y-X},max{X,Y+Y-X}]处。

现在3只小兔子的位置分别到了x,y,z(3只兔子长得一样,即三只兔子跳完之后的顺序可以变化)处,但是它们忘记一开始是怎么跳的了,想让你帮它们还原跳法。但这个问题非常easy,于是LYK要求你输出方案总数。

保证答案有解。

由于答案巨大,你只需输出答案对1e9+7取模后的结果就可以了。

输入格式(rabbits.in)

第一行3个数a,b,c。

第二行3个数x,y,z。

第三行一个数k。

数据保证3只兔子的起始位置a,b,c严格递增且3只兔子最终的位置x,y,z严格递增。

输出格式(rabbits.out)

一行表示方案总数。

输入样例1

0 2 5

0 2 5

2

输出样例1

3

输入样例2

0 2 4

0 2 4

2

输出样例2

2

样例解释

对于样例1:共有3种跳法,第一次跳完后的位置分别是{0,-2,5},{4,2,5},{0,8,5}。

数据范围

对于10%的数据k=1。J

对于30%的数据k<=10。

对于另外20%的数据a=x,b=y,c=z。

对于再另外20%的数据a-b=b-c。

对于再再另外20%的数据a,b,c与x,y,z之间不超过10步可达。

对于100%的数据k<=100,|a|,|b|,|c||x|,|y|,|z|<=10^18。

如果能由外往里跳,那么只能跳一个

中间那个可以往外跳,有向左和向右两种方式

所以跳的路径是一棵二叉树

设起始位置在A号节点,终止位置在B号节点

令f[i][j][k] 表示A 和 LCA的距离为i,B 和 LCA的距离为j,还剩下k步可以跳的方案数

一、对于一般的一对A和B(不在根节点,且LCA不是A或B)来说,有两种决策:

1、A向上跳,跳到 i-1 j  k-1

2、A向下跳,A往左往右跳一个样,跳到 i+1 j k-1,方案数*2

二、若A是LCA

如果B也是LCA,即A和B在同一个位置,那可以

1、A往上跳,跳到 i j+1 k-1

2、A往下跳,跳到 i+1 j k-1 方案数*2

如果B不是LCA,

1、A往上跳,跳到 i j+1 k-1

2、A往下跳,跳到非B所在的子树 i+1 j k-1;跳到B所在的子树 i j-1 k-1

注意,A有可能是二叉树的根节点,这样A不能向上跳

此时i=0,j>B的深度,特判这种情况

#include<cstdio>
#include<cstring>

using namespace std;

typedef long long LL;

const int mod=1e9+7;

#define N 101

LL a0[N],b0[N],c0[N];
LL x0[N],y0[N],z0[N];

int f[N][N][N];

int k1,k2;

int dfs(int i,int j,int k)
{
    if(!i && !j && !k) return 1;
    if(i+j>k) return 0;
    if(!i && j>k2) return 0;
    if(f[i][j][k]!=-1) return f[i][j][k];
    if(!i) 
    {
        if(!j) f[i][j][k]=(dfs(0,1,k-1)+dfs(1,0,k-1)*2%mod)%mod;
        else f[i][j][k]=((dfs(0,j+1,k-1)+dfs(0,j-1,k-1))%mod+dfs(1,j,k-1))%mod;
    }
    else f[i][j][k]=(dfs(i-1,j,k-1)+dfs(i+1,j,k-1)*2%mod)%mod; 
    return f[i][j][k];
}

int main()
{
    freopen("rabbits.in","r",stdin);
    freopen("rabbits.out","w",stdout);
    int k;
    scanf("%I64d%I64d%I64d%I64d%I64d%I64d",&a0[0],&b0[0],&c0[0],&x0[0],&y0[0],&z0[0]);
    scanf("%d",&k);
    bool root=false;
    while(k1<k)
    {
        if(b0[k1]-a0[k1]==c0[k1]-b0[k1]) break;
        if(b0[k1]-a0[k1]<c0[k1]-b0[k1])
        {
            k1++; 
            a0[k1]=b0[k1-1];
            b0[k1]=2*b0[k1-1]-a0[k1-1];
            c0[k1]=c0[k1-1];
        }
        else
        {
            k1++;
            a0[k1]=a0[k1-1];
            b0[k1]=2*b0[k1-1]-c0[k1-1];
            c0[k1]=b0[k1-1];
        }
    }
    while(k2<k)
    {
        if(y0[k2]-x0[k2]==z0[k2]-y0[k2]) break;
        if(y0[k2]-x0[k2]<z0[k2]-y0[k2])
        {
            k2++; 
            x0[k2]=y0[k2-1];
            y0[k2]=2*y0[k2-1]-x0[k2-1];
            z0[k2]=z0[k2-1];
        }
        else
        {
            k2++;
            x0[k2]=x0[k2-1];
            y0[k2]=2*y0[k2-1]-z0[k2-1];
            z0[k2]=y0[k2-1];
        }
    }
    int l1,l2; bool tag=false;
    for(l1=0;l1<=k1 && !tag;++l1)
        for(l2=0;l2<=k2 && !tag;++l2)
            if(a0[l1]==x0[l2] && b0[l1]==y0[l2] && c0[l1]==z0[l2]) tag=true; 
    l1--; l2--;
    memset(f,-1,sizeof(f));
    printf("%d",dfs(l1,l2,k));
}
View Code

考场爆零原因:用%d读long long

Summary

1、本场考试150分虽然是rank3,但150分的有8个,T3直接输出1拿到10分就可以脱颖而出

2、考场上的一分钟都不能放弃,到了最后也要垂死挣扎,特判之类的东西全打上,多扑腾会儿

3、T1正解是搜索,我在考场上是打表找规律,只找全了n<=6的,>6的只找到了m等于能取到的最大值和次大值的规律,期望是40分,结果后面60%的数据有40%的数据m是最/次大值,这就多得了40分,考场上还觉得没有什么用犹豫了好久才打上,所以如果写的是特判之类的,不要放过任何对的idea,说不定你就判到了数据呢。(对于这种搜索题数据为梯度内极端数据可能性比较大)

4、T2暴力80分,因为实际数据与题面中的数据描述不符,拿了70分,那个正解随机性算法是当时的我无论如何也想不到的,在这种情况下,一定要拿满暴力分

5、一定要特别注意long long的读入与输出,不仅仅是lld与I64d的问题,考场上用%d读long long,自己造的小数据没有问题,测试数据全>int。这种蠢到不能再蠢得问题不能出现第二次

6、加强搜索,T1竟然没看出来是道搜索题

7、谁说随机性的、正确率不是100%的算法就不可能成为正解了?在大量的操作下,错误率大大的降低。要注重一些非完美算法,也多思考一些非完美的解题思路(毕竟目前对我来说省选及以上难度比赛中想出正解的概率是很小的),不一定非要是有名字的算法呀!!

原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/8404293.html