第一季 停课模拟考试整理(完结)

———————10.11开缝线——————————————————-
今天停课第一次考试考了 T1 80+T2 0+T3 20 +T4 10 。
第一题说是数据错了80就满分,T2 考试没想明白不会,T3感觉能拿100分的可是弄最小生成树的时候把图弄乱了,导致后面跑最短路出问题了,只拿了20分。T4暴力模拟拿了10分。
题解:
T1
高精度加,减,乘。 而且保证数据全整数,减法第一个数一定大于第二个数。没什么好写的。
代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
char  s[100000];
struct Big
{
    int a[10000];
    int x;
};
Big operator + (Big A,Big B)
{
    int x=max(A.x,B.x);
    for(int i=1;i<=x;i++)
    {
        A.a[i]+=B.a[i];
        A.a[i+1]+=A.a[i]/10;
        A.a[i]%=10;
    }
    return A;
}
Big operator - (Big A,Big B)
{
    int x=max(A.x,B.x);
    for(int i=1;i<=x;i++)
    {
        A.a[i]-=B.a[i];
        if(A.a[i]<0)
        {
            A.a[i+1]-=1;
            A.a[i]+=10;
        }
    }
    return A;
}
Big D;
Big operator * (Big A,Big B)
{
    Big C=D;
    for(int i=1;i<=5000;i++)
    C.a[i]=0;
    for(int i=1;i<=A.x;i++)
    for(int j=1;j<=B.x;j++)
        C.a[i+j-1]+=A.a[i]*B.a[j];
    for(int i=1;i<=5000;i++)
    {
        C.a[i+1]+=C.a[i]/10;
        C.a[i]%=10;
    }
    return C;
}

Big A,B,C;
void out()
{
    int h=0;
    for(int i=4950;i>=1;i--)
    {
        int q=C.a[i];
        if(q!=0&&h==0)
        h=1;
        if(h==1)
        printf("%d",q);
        if(h==0&&i==1)
        printf("%d",0);
    }
}
int main()
{
    freopen("iphone.in","r",stdin);
    freopen("iphone.txt","w",stdout);
    char ha;
    cin>>ha;
    scanf("%s",s);
    int x=strlen(s);
    for(int i=0;i<x;i++)
        A.a[x-i]=s[i]-'0';  
    A.x=x;
    scanf("%s",s);
    x=strlen(s);
    for(int i=0;i<x;i++)
        B.a[x-i]=s[i]-'0';
    B.x=x;
    if(ha=='+')
    {
        C=A+B;
        out();
    }
    if(ha=='-')
    {
        C=A-B;
        out();
    }
    if(ha=='*')
    {
        C=A*B;
        out();
    }
    fclose(stdin);
    fclose(stdout);
    return 0;
}

T2
题目描述
loi 的 zkj 被班长 gz 派遣养兔子,为了实现规模化养殖,他很聪明地把很多个兔子窝建在一条笔直的道路旁,同时 zkj 比较懒,为了省事儿他要搭建规模都相等的兔子窝,所以每个兔子窝可以容纳的兔子数量都是相等的。在这条笔直的道路旁,每个兔子窝(除了第一个和最后一个)都直接和相邻的两个兔子窝相连接,一只兔子一年要吃掉一吨胡萝卜,zkj 每年都会往兔子窝投放胡萝卜,每个兔子窝获得的胡萝卜数是不一样的。每个兔子窝获得的胡萝卜既可以窝内解决也可以运到其他兔子窝里,在运输过程中,每公里要上贡一顿胡萝卜作为过路费。已知每个兔子窝这一年获得的胡萝卜数,并假设运输方案是最佳的,计算 zkj 最多能养多少只兔子。
输入描述
输入文件第一行包含一个整数 N,1<=n<=100000,表示兔子窝总数。接下来的 N 行每行包括两个整数 a 和 b,其中 1<=a<=1000000000,0<=b<=1000000000,分别表示兔子窝的位置(坐标)和该兔子窝获得的胡萝卜数所有兔子窝按其位置从小到大排序给出,注意问题一定存在正整数解。
输出描述
输出文件仅一行,包含一个整数,表示每个兔子窝最多能养的兔子数。
样例输入
4
20 300
40 400
340 700
360 600
样例输出
415

正解2分验证答案。二分最多能养多少只兔子。保证前面最优判断最后一个。注意从前往后移动的时候与0取个max,因为在路上可能变成负数。
代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
long long n;
long long jl[120000],hlb[120000],dq[120000];
int main()
{   
    freopen("rabbit.in","r",stdin);
    freopen("rabbit.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d%d",&jl[i],&hlb[i]);
    long long l=1,r=1e9+1,mid;
    while (r-l>1)
    {
        mid=(r+l)/2;
        for(int i=1;i<=n;i++)
            dq[i]=hlb[i];
        for(int i=1;i<n;i++)
        {
            if(dq[i]>mid)
            dq[i+1]+=max((long long)0,dq[i]-mid-jl[i+1]+jl[i]);
            if(dq[i]<mid)
            dq[i+1]-=mid-dq[i]+jl[i+1]-jl[i];
        }
        if(dq[n]>=mid) l=mid;
        else r=mid;
    }
    cout<<l<<endl;
    fclose(stdin);
    fclose(stdout);
    return 0;
}

T3
禁地
题目描述
ix 和木易来到了 loi 门派的禁地之所。但是因为有复杂的阵法禁制他们无法进入, 于是在禁制外开始思考。他们看到, 阵法是由 n 个从 1 到 n 标号的岛屿组成的, 岛屿之间由念力光线连接, 因为 ix 和木易拥有云中靴所以他们可以沿着念力光线通行, 即两个岛屿间只要有一条念力光线的存在, 那么他们就可以自由往返于两个岛屿间, 前提是他们的起始点要在其中的任意一个岛屿上。他们两人在阵法里不断穿梭游动着……渐渐的忘记了他们来时的目的。他们发现念力光线是有长度的, 于是 ix 想要计算一下连接阵法内各个岛屿使得各个岛屿都互相联通的最短光线长度, 但木易想要计算一下从他们现在所站的位置到阵法内任意一个岛屿的最短路径长度。 两人发生了争执, 因为声音过大激发了学长大神们留下的惩罚禁制之灵。 禁制之灵很不客气的让他们在 2s 之内计算出他们各自的问题, 但是 ix 和木易都是学过 oi 的所以很轻松的就切掉了, 禁制之灵便增大了难度, 它会多次询问并会在某两个岛屿之间添加一条念力光线。因为 Ix 和木易实在是太弱了, 都不会做, 于是找到了学信息奥赛的你, 请你帮他们解决这个问题。
输入格式
输入文件的第一行为两个正数 n, m 代表原阵法内的岛屿总数和念力光线总数。以下 m 行, 每行三个正数 u, v, l. 代表每条念力光线连接的两个点以及其长度。再一行只有一个正数 q, 代表操作数。接下来每行先是一个正数 p,
若 p 为 1 则后面跟着两个正数 s, t。 请输出从 s 岛屿到 t 岛屿的最短路径长度;(没有输出0);
若 p 为 2, 则输出连接阵法内各个岛屿使得各个岛屿都互相联通的最短光线长度;
若 p 为 3, 则后跟三个正数 a, b, d, 代表在 a, b 之间添加一条长度为 d 念力光线。 输出格式
与输入文件操作中 1, 2 操作数对应。
输入样例
5 8
1 2 4
2 3 6
3 4 2
4 5 6
1 3 2
1 3 8
2 5 3
4 1 5
5
1 1 5
2
3 1 5 1
1 1 5
2
输出样例
7
11
1
8
数据说明
0 <念力光线的长度<= 1000
保证所有岛屿都联通
数据共十个点, 对于:
N<= M<= Q<= 备注
点 1 10 100 10 询问中没有 2、3
点 2 10 100 1 询问中没有 1、3
点 3 10 100 10 询问中没有 3
点 4 100 1000 10
点 5 100 1000 100
点 6 100 1000 100
点 7 1000 10000 10
点 8 1000 10000 10
点 9 10000 100000 10
点 10 10000 100000 10
最短路+上最少生成树,注意要开两个结构体数组,因为最小生成树的排序会把图弄乱。
代码:

#include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>
using namespace std;
int n,m;
int inf=1e9;
struct bian 
{
    int f,t,d;
}b[200100];
bian c[200100];
int tot=0,first[200100],next[200100],dis[200100];
void build(int f,int t,int d)
{
    b[++tot]=(bian){f,t,d};
    c[tot]=(bian){f,t,d};
    next[tot]=first[f];
    first[f]=tot;
}
queue <int>  q;
bool used[200100];
void spfa(int x)
{
    for(int i=1;i<=n;i++)
        dis[i]=inf;
    dis[x]=0;
    q.push(x);
    used[x]=1;
    while (!q.empty())
    {
        int u=q.front();
        q.pop();
        used[u]=0;
        for(int i=first[u];i!=0;i=next[i])
        {
            int v=b[i].t;
            if(dis[v]>dis[u]+b[i].d)
            {
                dis[v]=dis[u]+b[i].d;
                if(used[v]==0)
                {
                    q.push(v);
                    used[v]=1;
                }
            }
        }
    }
}
int cp(bian a,bian b)
{
    return a.d<b.d;
}
int fa[200100];
int find(int x)
{
    if(fa[x]==x)
    return x;
    else 
    return fa[x]=find(fa[x]);
}
int zxscs()
{
    int ans=0;
    sort(c+1,c+tot+1,cp);
    for(int i=1;i<=n;i++)
        fa[i]=i;
    for(int i=1;i<=tot;i++)
    {
        int hi=c[i].f;
        int ha=c[i].t;
        if(find(hi)!=find(ha))
        {
            fa[find(hi)]=find(ha);
            ans+=c[i].d;
        }
    }
    return ans;
}
int main()
{
    freopen("forbidden.in","r",stdin);
    freopen("forbidden.out","w",stdout);
    scanf("%d%d",&n,&m);
    int qq,ww,ee;
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&qq,&ww,&ee);
        build(qq,ww,ee);
        build(ww,qq,ee);
    }
    int q,tt,s,t,xx,yy,zz;
    scanf("%d",&q);
    for(int i=1;i<=q;i++)
    {
        scanf("%d",&tt);
        if(tt==1)
        {
            scanf("%d%d",&s,&t);
            spfa(s);
            printf("%d\n",dis[t]);
        }
        if(tt==2)
        {
            printf("%d\n",zxscs());
        }
        if(tt==3)
        {
            scanf("%d%d%d",&xx,&yy,&zz);
            build(xx,yy,zz);
            build(yy,xx,zz);
            m+=2;
        }
    }
    fclose(stdin);
    fclose(stdout);
    return 0;
}

T4
4 基地占领
伟大的 cp 是一位懂得放松的好同学。他在放松的时候,经常玩一个名叫 loicraft 的即使战略类游戏。这个游戏是有红蓝双方组成的,红方负责攻击,而蓝方负责挨揍。伟大的 cp 当然要当红方了。他经过侦查发现,蓝方的基地有 n 个,这 n 个基地恰好组成了一行的线性结构,从东到西依次标记为 1 到 n。比赛刚开始时,每一个基地都是完好的。比赛开始后,cp 学长为了尽早的打败对方,他使用了一种极其坑爹的武器:灵符。每一个灵符可以打坏区间[l,r]的全部基地。cp 共有 m 个灵符,因此他一定会攻击 m 次,每次攻击他都会攻击一个区间,但是,由于 cp 眼神不太好,因此他不能保证轰炸的这 m 个区间中不会出现重叠,也不能够保证这些区间不会出现包含一类的关系。换句话说,一个基地可能会被轰炸好多次。现在,告诉你蓝方所有的基地数量 n、cp 的灵符数量 m 以及他每次攻击的区间[l,r],请你输出他每次攻击后蓝方还没有被攻击的基地的数量。
输入格式
第一行两个整数 n(≤10的6次方),m(≤10的6次方).
接下来共有 m 行,每行两个整数 l,r 表示他这次攻击的区间是[I,r],输入数据保证 1≤ l≤ r ≤ n.输出格式共 m 行,每行一个整数,表示此次攻击后蓝方还没有被攻击的基地的数量。
样例输入
10 3
3 7
1 2
2 5
样例输出
5
3
3
样例说明
第一次攻击[3,7]之后,还剩 1、2、8、9、10 号基地未被攻击。
第二次攻击[1,2]后,还剩 8、9、10 号基地未被攻击。
第三次攻击[2,5]后,还剩 8、9、10 号基地未被攻击。
其中,2,3,4,5 号基地被攻击了 2 次。
考试没想到是并查集!线段树也能做。但我不会打线段树,也不会并查集。所以就只能暴击10分滚粗了。并查集记录左边没摧毁的点的父亲,他的的父亲是从他开始往右第一个没被摧毁的点(包括他自己)。不过递归的并查集栈溢出了,需要while的并查集。但在noip中据说不会栈溢出。
代码

#include <iostream>
#include <cstdio>
using namespace std;
int fa[1000005];
int find(int x)
{
    if(fa[x]==x)
    return x;
    else 
    return fa[x]=find(fa[x]);
}
/*int find(int x)
{
    int r = x;
    while(r != fa[r])
        r = fa[r];
    int t;
    while(x != r)
    {
        t = fa[x];
        fa[x] = r;
        x = t;
    }
    return r;
}*/
void read(int &a)
{
    a=0;char c=getchar();
    while(c<'0'||c>'9')
        c=getchar();
    while(c>='0'&&c<='9')
    {
        a*=10;a+=c-'0';
        c=getchar();
    }
}
int main()
{
    freopen("craft.in","r",stdin);
    freopen("craft.out","w",stdout);
    int n,m;
    read(n);
    read(m);
    for(int i=1;i<=n+1;i++)  //如果摧毁区间x到n会没有给n+1赋值的话=0会死循环
        fa[i]=i;
    int p,l,r,cnt=n;
    for(int i=1;i<=m;i++)
    {
        read(l);read(r);
        p=find(l);
        while (p<=r)
        {
            cnt--;
            fa[p]=p+1;
            p=find(p);
        }
        printf("%d\n",cnt);
    }   
    fclose(stdin);
    fclose(stdout);
    return 0;
}

呼呼~~整理完了。
- - - - - - - - - - - - - - - - - - - - - 明天你好 - - - - - - - - - - - - - - - - - - - - - - - - - -
今天没考试上午自己做了两个题,下午愉快的羽毛球比赛,回来机房门还没开,在门外跟dyl,lxl,jhz 玩了一会小学生玩的游戏(233)。晚上整理整理明天准备考试。
- - - - - - - - - - - - - -太阳还会升起,学习还得继续 - - - – - - - – - - - - - - - - - - - -

今天上午的模拟考试10分滚粗了。而且没有任何水平,只要第一题cout<<-1;就10分不说成绩了来说说考试题跟总结。题目据说是去年与青岛二中的胡策题。T1一个迷宫搜索打傻了。T2一个恶心的DP不会。T3正解栈模拟没看出来当时,当时没往栈啊,队列啊这些数据结构上(ˇˍˇ) 想~,数组不行就暴力了结果打ci了。
T1
A 迷宫(maze2.pas/c/cpp)
TL:1S ML:128MB
【Description】
你所在的迷宫可以用 N 行 M 列的矩阵来描述:
图标 含义
‘#’墙,无法通过。
地面,可以通过。
小写字母(a、b、c、…、z) 钥匙,可以打开标有对应大写字母的门大写字母(A、B、C、…、Z) 门,可以被标有对应小写字母的钥匙打开
‘$’ 你的初始位置& 迷宫的出口位置
迷宫的四周都有墙,所以你无法走出这片 N*M 的区域,只能从”&”处离开迷宫,你只能向东西南北四个方向走。你的任务是,计算出走出迷宫需要的最少步数是多少?
【Input】
第 1 行两个正整数 N 和 M,表示迷宫的长和宽;
第 2 行一个正整数 P,表示门和钥匙的数量;
第 3 行至第 N+2 行,描述整个迷宫。
【Output】
一个整数,为走出迷宫需要的最少步数或-1(如果不可能走出迷宫)。

///样例手打输入,复制的话会出现神奇问题。
【Sample Input】

5 5
1
&A..$
####.
…#.
.#.#.
a#…
【Sample Output】
28

【Sample Input】
1 4
1
&aA$

【Sample Output】
-1
【Hint】
对于 30%:1 <= N, M <= 15
另外存在 10%:P=0
另外存在 10%:P=1
另外存在 20%:P=2
对于 100%:1<=N,M<=50,0<=P<=10,保证迷宫中”$”、”&”和所有大小写字母只出现一次,钥匙和门的标号只会出现字母表中的前 P 个字母。
题解:开[x][y][k]三维数组记录一下状态,跑bfs。二进制处理钥匙数。

#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;
struct pp
{
    int x,y,k,now;
};
queue <pp> q;
int n,m,p;
bool used[55][55][1500];
char map[55][55];
const int dx[]={0,-1,0,1,0};
const int dy[]={0,0,1,0,-1};
int sx,sy,ex,ey;
int bfs(int sx,int sy,int ex,int ey)  //bfs遍历不同的状态 
{
    pp s;
    s.x=sx;s.y=sy;
    s.k=0;s.now=0;
    q.push(s);
    used[s.x][s.y][s.k]=1;
    while (!q.empty())
    {
        pp f=q.front();
        q.pop();
        if(f.x==ex&&f.y==ey)
            return f.now;
        else 
        {
            for(int i=1;i<=4;i++)
            {
                int nx=f.x+dx[i];
                int ny=f.y+dy[i];
                if(nx>=1&&nx<=n&&ny>=1&&ny<=m&&!used[nx][ny][f.k]&&map[nx][ny]!='#')
                {
                    pp next;
                    next.x=nx;
                    next.y=ny;
                    next.now=f.now+1;
                    next.k=f.k;
                    if(map[nx][ny]>='a'&&map[nx][ny]<='z')   //处理拿到第几把钥匙 
                    {
                        used[nx][ny][f.k]=1;
                        next.k |= 1<<(map[nx][ny]-'a');
                        used[next.x][next.y][next.k]=1;
                        q.push(next);
                    }
                    else if(map[nx][ny]>='A'&&map[nx][ny]<='Z')  //如果有钥匙就可以开门继续搜索 
                    {
                        if(next.k&(1<<(map[nx][ny]-'A')))
                        {
                            used[nx][ny][f.k]=1;
                            q.push(next);
                        }
                    }
                    else 
                    {
                        used[nx][ny][f.k]=1;
                        q.push(next);
                    }
                }
            }
        }
    }
    return -1;    //不行返回-1 
}
int main()
{
    freopen("maze2.in","r",stdin);
    freopen("maze2.out","w",stdout);
    scanf("%d%d%d",&n,&m,&p);
    for(int i=1;i<=n;i++)
    {
        scanf("%s",map[i]+1);
        for(int j=1;j<=m;j++)
        {
            if(map[i][j]=='$')
            {
                sx=i;
                sy=j;   
            }
            if(map[i][j]=='&')
            {
                ex=i;
                ey=j;
            }
        }
    }
    int ans=bfs(sx,sy,ex,ey);
    printf("%d",ans);
    fclose(stdin);
    fclose(stdout);
    return 0;
}

T2
B 三重镇(tritown.pas/c/cpp) TL:2S ML:128MB
【Description】
小西同学最近喜欢上了 iOS 游戏《三重镇 Triple Town》。游戏之余,小西也在思考如何才能在这个游戏中获得更高的分数。 游戏在一个 1 * 3 的地图中进行。初始的时候,所有的格子都是空白位置。游戏给定一个建造序列,玩家按照此建造序列依次选择空白位置建造相应的建筑单位。建筑有九个不同的等级,标注为 L1,L2….,L9。当玩家在一个空白位置建造单位之后,有可能引起反应。反应的构成条件是: 当前的三个格子中的建筑物都是同一等级的, 则这三个建筑将合并为一个下一等级的建筑,此建筑的位置
为最后建造的建筑单位位置,其他位置将变回空格。另外需要注意的是,L9 为建筑的最高等级,所以三个 L9 并不会合并。上图是一种可能的反应情况。其中灰色的表示最后建造的建筑。游戏的得分取决于玩家建造和反应生成的单位。 建造或者反应生成建筑单位就可以获得相应的分数。不同等级建筑的得分表如下: 建筑 L1 L2 L3 L4 L5 L6 L7 L8 L9得分 4 20 100 500 1500 5000 20000 100000 500000
上图中,我们初始建造了 3 个 L2,获得 60 分。之后反应出了一个 L3,得到 100 分。总共获得 160 分。
游戏中还设有两种道具,分别为“星星”和“炸弹”。
在游戏开始时,玩家被给定 p 个星星道具和 q 个炸弹道具,玩家可以在任意时刻使用。两者功能如下:
“星星”道具: 可以放置在一个空格位置。当星星被放置时,星星会自动变为能引起反应的最高等级建筑。当在该位置不能引起任何反应时,星星变为 L1。
例如,当前有两个位置上是 L5,此时放置星星,则会变为 L5,同时导致一次反应,最后放置星星的位置上出现了一个 L6,其他位置都是空白。
“炸弹”道具: 炸弹道具可以放在在一个有建筑的位置上,作用为炸掉这个建筑并将该位置恢复为空格。当使用炸弹时,得分将扣除被炸掉的建筑的一半分数(即得分为负数)。 在游戏的进行过程中,玩家必须按照给定的顺序进行建造, 而且不能跳过任何一个给定的建筑, 但可以随时穿插使用两种道具,也可以随时结束游戏。游戏的目标是,通过合理的操作,取得最高的分数。
【Input】
第一行两个整数 p, q。
第二行一个整数 n。
第三行 n 个整数,表示所有给定的建筑的等级。保证输入的数一定在[1..9]内
【Output】
一个整数,表示答案。
【Sample Input】
1 1
5
4 5 5 5 6
【Sample Output】
39750
【Hint】
STEP Score
【4, 0, 0】 500
【0, 0, 0】使用炸弹 250
【5, 0, 0】 1750
【5, 5, 0】 3250
【5, 5, 0】->【0, 0, 6】 9750
【0, 6, 6】 14750
【7, 0, 0】使用星星 39750
对于 20%:0 <= n, p, q <= 5
对于另外 20%:p=q=0
对于 100%:N <= 50, p,q <= 30
题解:
貌似是个6维DP,害怕。题解看不明白,留个题面纪念一下吧。代码写个暴力吧。

#include<iostream>
#include<cstdio>
using namespace std;
int num[4];
int sco[10] = {0,4,20,100,500,1500,5000,20000,100000,500000};
int main()
{
    freopen("tritown.in","r",stdin);
    freopen("tritown.out","w",stdout);
    int p,q,n;
    long long ans = 0;
    scanf("%d%d%d",&p,&q,&n);
    int pos = 1;
    for(int i = 1 ; i <= n ; i ++)
    {
        int s;
        scanf("%d",&s); 
        if(num[1]!=0 && num[2]!=0 && num[3]!=0)
        {
            if(num[1]==num[2]&&num[2]==num[3])  //不能写成num[1]==num[2]==num[3]  !!!
            {
                num[3]++;
                ans+=sco[num[3]];
                num[1]=0;
                num[2]=0;
            } 
            else 
            {
                cout<<ans;
                return 0;
            }
        }
        if(num[1]==0)
        {
            num[1] = s;
            ans += sco[s];
            continue;
        } 
        if(num[2]==0)
        {
            num[2] = s;
            ans += sco[s];
            continue;
        }
        if(num[3]==0)
        {
            num[3] = s;
            ans += sco[s];
            continue;
        }
    }
    cout<<ans;
    fclose(stdin);
    fclose(stdout);
    return 0;
}

/*
0 0
17
2 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9
1881360

0 0
15
3 3 3 4 4 5 5 6 6 7 7 8 8 9 9
1881300

*/

T3
C 加密(encryption.pas/c/cpp) TL:1S ML:128MB
【Description】
有一个仅含小写字母的字符串,我们把它按如下方法加密:
STEP1:把所有连续的相同字母都用一个字母代替。比如 aaabbbb 被替换为 ab。
STEP2:在随机的位置插入两个相同的小写字母。重复 STEP2 很多次。
下面是一个加密的实例
初始字符串 ssstieerrrliiittz
STEP1 之后 stierlitz
插入 dd stddierlitz
插入 aa stdaadierlitz
插入 ww wwstdaadierlitz
现在我们给定加密后的字符串,求执行 STEP1 之后的字符串是什么。
【Input】
一个字符串,表示加密后的字符串。
【Output】
一个字符串,表示执行 STEP1 之后的字符串。
【Sample Input】
wwstdaadierlitz
【Sample Output】
stierlitz
【Hint】
对于 30%:N<= 1000
对于 70%:N<=100000
对于 100%:N<=1000000
题解 :
就是个栈模拟,当时我没忘这上面想!!!并查集也能做,栈模拟多简单so代码为栈模拟。(发现并查集好神啊连着两次考试最后一题都能做链表加路径压缩等于并查集不知道下次考试还行不行QWQ)

#include <iostream>
#include <cstring>
#include <cstdio>
#include <stack>
using namespace std;
char a,b,c;
char q[1001000];
char ss[1001000];
stack <char> s;
int main()
{
    freopen("encryption.in","r",stdin);
    freopen("encryption.out","w",stdout);
    scanf("%s",ss);
    int x=strlen(ss);
    for(int i=0;i<x;i++)
    {
        if(s.empty())   //不能写i==0,要写栈为空!!!有可能中途把栈弹空了
            s.push(ss[i]);
        else
        {
            b=s.top();
            if(ss[i]==b)
                s.pop();
            else 
                s.push(ss[i]);
        }
    }
    int t=0;
    while (!s.empty())
    {
        c=s.top();
        s.pop();
        t++;
        q[t]=c;
    }   
    for(int i=t;i>=1;i--)
    cout<<q[i];
    fclose(stdin);
    fclose(stdout);
    return 0;
}

两天没更新╮(╯_╰)╭了QAQ昨天做的洛谷的题,晚上开会没时间了。今天补上。
240,t1 100,t2 70,t3 70一共考了50,T1 20,别人暴力都70,T2暴力 30还可以。T3不会没看明白,
T1找了半天应是m,用成了n,然后就有60分了,还是w了一个点,当时表示很不理解,看了数据,结果分段函数大错了,给的数据有可能前一个点大于后一个点,我直接从前一个点for到后一个点,没判断,当时没想全!!!,以后打代码一定要想好,认真打,哪怕慢一点也不能犯傻x错误,不光难找浪费时间而且意义不大。就这样70分成功的到了20分,100分,变成了50分滚粗。
做题感受,当时看T1觉得能做但样例麻烦没仔细看去看T2感觉貌似也可以做,最起码都读懂题意了,看T3看了一遍没明白题意,看暴力也不会打直接gg了,去做前两道题,由于T2样例解释比T1简单,so先做T2,由于估计错误时间复杂度拿到了30分,花了我1个半小时,(太长了)然后仔细看T1,看明白了,但我与需要一中快速进行区间加的方法,线段树貌似可以,但我不会23333。只好暴力打,然后看了一眼数据范围30%的数据特别水,然后特蛋疼的打了一个分段函数,结果出事了233。而且当时打的时候有点急时间安排不大合理,所以就…。考完我知道学回了一个O(n)支持区间加的东西,叫差分数组,比如在 (z,y ) 这个区间加上一个1,只需要开一个cf[z]+1,cf[y]-1,就可以了
查询的时候去一下加和就可以。
T1
题目描述
该铁路经过N个城市,每个城市都有一个站。不过,由于各个城市之间不能协调好,于是乘车每经过两个相邻的城市之间(方向不限),必须单独购买这一小段的车票。第i段铁路连接了城市i和城市i+1。如果搭乘的比较远,需要购买多张车票。第i段铁路购买纸质单程票需要Ai博艾元。虽然一些事情没有协调好,各段铁路公司也为了方便乘客,推出了IC卡。对于第i段铁路,需要花Ci博艾元的工本费购买一张IC卡,然后乘坐这段铁路一次就只要扣Bi元。IC卡可以提前购买,有钱就可以从网上买得到,而不需要亲自去对应的城市购买。工本费不能退,也不能购买车票。每张卡都可以充值任意数额。对于第i段铁路的IC卡,无法乘坐别的铁路的车。Uim现在需要出差,要去M个城市,从城市P1出发分别按照P1,P2,P3…PM的顺序访问各个城市,可能会多次访问一个城市,且相邻访问的城市位置不一定相邻,而且不会是同一个城市。
现在他希望知道,出差结束后,至少会花掉多少的钱,包括购买纸质车票、买卡和充值的总费用。
输入输出格式
输入格式:
第一行两个整数,N,M。
接下来一行,M个数字,表示Pi
接下来N-1行,表示第i段铁路的Ai,Bi,Ci
输出格式:
一个整数,表示最少花费
输入输出样例
输入样例#1:
9 10
3 1 4 1 5 9 2 6 5 3
200 100 50
300 299 100
500 200 500
345 234 123
100 50 100
600 100 1
450 400 80
2 1 10
输出样例#1:
6394
说明
2到3以及8到9买票,其余买卡。
对于30%数据 M=2
对于另外30%数据 N<=1000 ,M<=1000
对于100%的数据 M,N<=100000,Ai,Bi,Ci<=100000
代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int a[100100],b[100100],c[100100],sum[100100],q[100100];
int dq,n,m,x,y;
long long ans=0;
int main()
{
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    scanf("%d%d",&n,&m);
    scanf("%d",&dq);
    for(int i=1;i<m;i++)
    {
        scanf("%d",&q[i]);
        x=min(q[i],dq);
        y=max(q[i],dq);
        sum[x]++;
        sum[y]--;
        dq=q[i];    
    }
    for(int i=1;i<n;i++)
    scanf("%d%d%d",&a[i],&b[i],&c[i]);
    long long tot=0;
    for(int i=1;i<=n;i++)
    {
        tot+=sum[i];
        ans+=min(tot*a[i],tot*b[i]+c[i]);
    }
    printf("%lld",ans);
    fclose(stdin);
    fclose(stdout);
    return 0;
}

T2
题目描述
一条道路上,位置点用整数A表示。
当A=0时,有一个王宫。当A>0,就是离王宫的东边有A米,当A<0,就是离王宫的西边有A米。道路上,有N个住宅从西向东用1-N来标号。每个住宅有一个人。住宅只会存在于偶数整数点。该国国王认为,国民体质下降,必须要多运动,于是下命令所有人都必须出门散步。所有的国民,一秒钟可以走1米。每个国民各自向东或者向西走。这些方向你是知道的。命令发出后所有人同时离开家门开始散步。然而该国的国民个都很健谈,如果在散步途中两个人相遇,就会停下来交谈。正在走路的人碰到已经停下来的人(重合)也会停下来交谈。一但停下来,就会聊到天昏地暗,忘记了散步。现在命令已经发出了T秒,该国有Q个重要人物,国王希望能够把握他们的位置。你能帮他解答吗?
输入输出格式
输入格式:
第一行是3个整数,N,T,Q
接下来N行,每行两个整数Ai,Ri。Ai是家的坐标,如果Ri是1,那么会向东走,如果是2,向西。数据保证Ai是升序排序,而且不会有两个人初始位置重合。
接下来Q行,每行一个整数,表示国王关心的重要人物。
输出格式:
Q行,每行一个整数,表示这个人的坐标。
输入输出样例
输入样例#1:
6 6 4
-10 1
-6 2
-4 1
2 1
6 2
18 2
2
3
4
6
输出样例#1:
-8
2
4
12
说明
20%数据 N<=100,T<=10000
另外20%数据 N<=5000
另外20%数据 从最西边数起连续的若干国民全部往东,剩下的全部往西
100%数据 Ai为偶数,|Ai|<=10^18,|T|<=10^18,1<=Q<=N<=100000.

#include <iostream>
#include <cstdio>
using namespace std;
struct ha
{
    long long x,y;
}a[100100];
long long n,t,q,dq,jl;
int main()
{
    scanf("%lld%lld%lld",&n,&t,&q);
    for(int i=1;i<=n;i++)
        scanf("%lld%lld",&a[i].x,&a[i].y);
    int i = 1;
    while(a[i].y == 2 && i <= n)
        a[i].x -= t,i ++;
    long long z=0,y=0,l = 0,r = 0,mid;
    for(;i<=n;i++)
    {
        if(a[i].y==1&&z==0)
            z=i;
        if(a[i].y==1&&a[i+1].y==2)
            l=a[i].x;
        if(a[i].y==2&&y==0)
            y=a[i].x;
        if((a[i].y==2&&a[i+1].y==1) || i == n)
            r=i;
        if(z!=0&&y!=0&&r!=0&&l!=0)
        {
            mid=(l+y)/2;
            for(int j=z;j<=r;j++)
            {
                if(a[j].x<mid&&a[j].x+t<mid)
                    a[j].x+=t;
                else if(a[j].x>mid&&a[j].x-t>mid)
                    a[j].x-=t;
                else 
                    a[j].x=mid;
            }
            z=0,y=0,r=0,l=0;
        }
    }
    i = n;
    while(a[i].y == 1 && i > 0)
        a[i].x += t,i --;
    int ha;
    for(int i=1;i<=q;i++)
    {
        scanf("%d",&ha);
        printf("%lld\n",a[ha]);
    }
    return 0;
}

完活O(∩_∩)O~~

————————————————233————————————-
考了10分,第一题卡输入,结果我输入进来不会搜索了。第二题想到怎么做,但代码实现不会,花了太长时间,第三题没做。第二题应该55分的,结果最后没时间检查代码错了一个变量,并且数组开小了所以只有10分。
DQS 的语文学习计划
题目描述
众所周知,DQS 的语文从不及格(雾),这天他进入了翡翠梦境想要学习
语文,翡翠之神告诉他:需要找到所有的语文之晶才能使他的作文达到
及格!翡翠梦境是由 n*m 个汉字(词语)组成的矩阵,矩阵中含有两种汉字(词
语) :井号,杠在翡翠梦境中,对于两点翡翠能量,如果他们的曼哈顿距离(对于
A(x1,y1)和 B(x2,y2),A 和 B 之间的曼哈顿距离为|x1-x2|+|y1-y2|)小
于等于 2。那么这两个点就属于一个语文之晶……DQS 一边欣赏着美丽的语文之晶,一边数着所有语文之晶的数量。伴着歌声和舞蹈,度过了快乐的语文学习之夜。
输入描述
第一行,两个数 n 和 m。(1<=n,m<=100)
接下来一共 n 行,每行 m 个汉字(词语)。对于第 i 行第 j 个汉字(词语),如果其为“杠”,那么表示该点没有能量,如果其为“井号”,那么表示该点有能量。不可能出现其他的字符。每个输入的汉字(词语)之间有空格
输出描述
第一行,一个数 s。
样例输入
19 48
杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠
杠 杠 杠 井号 井号 井号 井号 杠 杠 杠 杠 杠 井号 杠 杠 杠 杠 杠 井号 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 井号 井号 井号 井号 杠 杠 杠
杠 杠 井号 井号 井号 井号 井号 井号 杠 杠 杠 杠 井号 杠 杠 杠 杠 杠 井号 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 井号 井号 井号 井号 井号 井号 杠 杠
杠 井号 井号 井号 井号 井号 井号 井号 井号 杠 杠 井号 杠 井号 杠 杠 杠 井号 杠 井号 井号 井号 井号 井号 杠 杠 井号 杠 井号 井号 杠 井号 井号 杠 杠 杠 井号 杠 杠 井号 井号 井号 井号 井号 井号 井号 井号 杠
杠 井号 井号 井号 杠 杠 井号 井号 井号 杠 杠 井号 杠 井号 杠 杠 杠 井号 杠 井号 杠 杠 杠 杠 井号 杠 井号 井号 杠 井号 井号 杠 杠 井号 杠 杠 井号 杠 杠 井号 井号 井号 杠 杠 井号 井号 井号 杠
杠 井号 井号 井号 杠 杠 井号 井号 井号 杠 杠 井号 杠 杠 井号 杠 井号 杠 杠 井号 井号 井号 井号 井号 井号 杠 井号 杠 杠 井号 杠 杠 杠 井号 杠 井号 杠 杠 杠 井号 井号 井号 杠 杠 井号 井号 井号 杠
杠 井号 井号 井号 井号 井号 井号 井号 井号 杠 杠 井号 杠 杠 井号 杠 井号 杠 杠 井号 杠 杠 杠 杠 杠 杠 井号 杠 杠 井号 杠 杠 杠 杠 井号 井号 杠 杠 杠 井号 井号 井号 井号 井号 井号 井号 井号 杠
杠 杠 井号 井号 井号 井号 井号 井号 杠 杠 杠 井号 杠 杠 杠 井号 杠 杠 杠 井号 井号 井号 井号 井号 井号 杠 井号 杠 杠 井号 杠 杠 杠 杠 杠 井号 杠 杠 杠 杠 井号 井号 井号 井号 井号 井号 杠 杠
杠 杠 杠 井号 井号 井号 井号 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 井号 杠 杠 杠 杠 杠 井号 井号 井号 井号 杠 杠 杠
杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 井号 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠
杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠
杠 杠 杠 井号 井号 井号 杠 杠 井号 杠 杠 杠 杠 杠 杠 杠 杠 井号 杠 杠 杠 杠 杠 杠 井号 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠
杠 杠 井号 杠 杠 杠 井号 杠 井号 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 井号 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠
杠 井号 杠 杠 杠 杠 杠 杠 井号 杠 井号 井号 杠 杠 井号 杠 井号 井号 杠 杠 井号 井号 杠 井号 井号 井号 杠 井号 杠 井号 井号 杠 井号 井号 井号 杠 杠 井号 井号 井号 杠 井号 杠 杠 井号 井号 杠 杠
杠 井号 杠 杠 杠 杠 杠 杠 井号 井号 杠 杠 井号 杠 井号 井号 杠 井号 杠 井号 杠 杠 杠 杠 井号 杠 杠 井号 井号 杠 杠 井号 杠 杠 杠 井号 井号 杠 杠 杠 井号 井号 杠 井号 杠 杠 杠 杠
杠 井号 杠 杠 杠 杠 杠 杠 井号 杠 杠 杠 井号 杠 井号 杠 杠 井号 杠 杠 井号 杠 杠 杠 井号 杠 杠 井号 杠 杠 杠 井号 杠 杠 杠 井号 井号 杠 杠 杠 杠 井号 杠 杠 井号 杠 杠 杠
杠 杠 井号 杠 杠 杠 井号 杠 井号 杠 杠 杠 井号 杠 井号 杠 杠 井号 杠 杠 杠 井号 杠 杠 井号 杠 杠 井号 杠 杠 杠 井号 杠 杠 杠 井号 井号 杠 杠 杠 井号 井号 杠 杠 杠 井号 杠 杠
杠 杠 杠 井号 井号 井号 杠 杠 井号 杠 杠 杠 井号 杠 井号 杠 杠 井号 杠 井号 井号 杠 杠 杠 井号 杠 杠 井号 杠 杠 杠 井号 杠 杠 杠 井号 杠 井号 井号 井号 杠 井号 杠 井号 井号 杠 杠 杠
杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠 杠
样例输出
4
数据范围及提示
swc:题目简单  数据无梯度.
输入建议用 string

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
char s[100];
int mp[120][120];
const int dx[]={0,0,0,0,0,-1,-2,1,2,-1,1,-1,1};
const int dy[]={0,-2,-1,1,2,0,0,0,0,-1,1,1,-1};
int n,m,z,ans=0;
/*void dfs(int x,int y)
{
    for(int i=1;i<=12;i++){
            int nx=x+dx[i];
            int ny=y+dy[i];
            if(nx>=1&&nx<=n&&ny>=1&&ny<=m&&mp[nx][ny]==1)
            {
                mp[nx][ny]=0;
                dfs(nx,ny);
            }
        }
    return ;
}*/
struct lc
{
    int x,y;
};
queue <lc> q;
void bfs(int x,int y)
{
    lc f;
    f.x=x;
    f.y=y;
    q.push(f);
    while (!q.empty())
    {
        f=q.front();
        q.pop();
        for(int i=1;i<=12;i++)
        {
            int nx=f.x+dx[i];
            int ny=f.y+dy[i];
            if(mp[nx][ny]==1&&nx>=1&&nx<=n&&ny>=1&&ny<=m)
            {
                mp[nx][ny]=0;
                lc nxt;
                nxt.x=nx;
                nxt.y=ny;
                q.push(nxt);
            }
        }
    }
}
int main()
{
    //freopen("chinese.in","r",stdin);
    //freopen("chinese.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            scanf("%s",s);
            z=strlen(s);
            if(z==2)
            mp[i][j]=0;
            if(z==4)
            mp[i][j]=1;
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(mp[i][j]==1){
                mp[i][j]=0;
                bfs(i,j);
                ans++;
            }
        }
    }
    printf("%d",ans);
    //fclose(stdin);
    //fclose(stdout);
    return 0;
}

dqs 的农场
题目描述
众所周知
dqs 因上课不好好睡觉被班主任请回了家里!dqs 回到家发现家里还有农场,于是他决定种些什么,几个月后 dqs 发现好像没有水的话植物并不能活下来╮(╯▽╰)╭于是 dqs 决定将水引入到他的边长为 n 的农场。他准备通过挖若干井,并在各块田中修筑水道来连通各块田地以供水。在第 i 号田中挖一口井需要花费 W_i 元。连接 i 号田与 j 号田需要 P_ij 元。请求出 dqs 需要为使整个农场的每一块田地全部获得供水所需要的钱数。
输入描述
第 1 行为一个整数 n。
第 2 行 n 个整数,分别为 W_1 到 W_n。
第 3 到 n + 2 行为一个矩阵,表示需要的经费 P_ij。
输出描述
只有一行,为一个整数,表示所需要的钱数。
样例输入
4
5 4 4 3
0 2 2 2
2 0 3 3
2 3 0 4
2 3 4 0
样例输出
9
数据范围及提示
对于 30 % 的数据:1 <= n <= 5 , 1 <= P_ij , W_i <=100;
对于 60 % 的数据:1 <= n <= 50 , 1 <= P_ij , W_i <= 5000;
对于 100 % 的数据:1 <= n <= 300 , 1 <= P_ij , W_i <= 100000;
样例解释:在第 4 号田挖井,花费 3,连接 1 – 2 号田,花费 2,连接
1 – 4 号田,花费 2 ,连接 1 – 3,花费 2,总花费 9.
题解:虚拟一个超级零点,是它可以到达任意一块田地并且权值为在这块田打水井的花费。

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int jing[101000];
int n,qq;
struct bian
{int f,t,d;}c[110000];
int tot=0;
void build(int f,int t,int d)
{c[++tot]=(bian){f,t,d};}
int fa[101000];
int find(int x)
{
    if(fa[x]==x)
    return x;
    else 
    return fa[x]=find(fa[x]);
}
bool cp(bian a,bian b)
{return a.d<b.d;}
int ans=0;
void Kruskal()
{
    sort(c+1,c+1+tot,cp);
    for(int i=1;i<=tot;i++)
    {
        int x=c[i].f;
        int y=c[i].t;
        if(find(x)!=find(y))
        {
            fa[find(x)]=find(y);
            ans+=c[i].d;
        }
    }
    return ;
}
int main()
{
//  freopen("farmer_m.in ","r",stdin);
//  freopen("farmer_m.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        fa[i]=i;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&jing[i]);
        build(0,i,jing[i]);  //建超级零点
        build(i,0,jing[i]);
    }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            scanf("%d",&qq);
            build(i,j,qq);
        }
    Kruskal();
    printf("%d",ans);
    //fclose(stdin);
    //fclose(stdout);
    return 0;
}

T3不是很懂唉不写了先。

——————–10.18——————————–胡策第一天——————-
感觉好奇怪qaq,四道题100分,今天忙着出题也没大改完,明天T3dp,T4暴力补上。
T1 没看出来是斐波那契数(之前我竟然不知道)20打表,T2打了个一个while(1)时间复杂度O(n),可是数据10亿得 二分 logn,得了70,应该80,那个点读题不认真,没考虑,就是n==1的时候不需要管子。T3dp,先跑一边01背包,然后完全背包。dp早忘了,根本没学会,10暴力贪心了。T4进制转换问题不懂。。。。。

Problem 1 DQS 要讲课
题目描述 DQS 是一个学习认真的学生,老师也对他赞誉有加,很是欣赏。于是,DQS 被老师叫到讲台上讲题。众所周知,DQS 比较胖,所以他希望找到讲台的某个点,也就是黄金分割点((√5 -1)/2≈0.61803398874989484820458683436564……)来使他被看起来更加美观。DQS 没有计算器,他只能用分数逐渐逼近这个位置。输入描述 输入文件只有一行,这一行有一个数 N,表示逼近该位置的分数分母≤N。
输出描述 输出文件只有一行,这一行有一个分数,格式为“x/y”,为你所输出
的分数。
样例输入 7
样例输出 3/5
数据范围及提示 对于 20%数据 1<=N<=10
对于 100%数据 1≤N≤10^19
数据较大用 unsigned long long 存储
题解:打表找规律,晚上红太阳lc刚教了我QAQ。
打表代码:

#include<iostream>
#include<cstdio>
#include<bits/stdc++.h>
using namespace std;

int main()
{
    double p=sqrt(5.0);p=p-1.0;
    p/=2;
    for(int n=1;n<=100;n++)
    {
        double dq=1e9;
        int p1,p2;
        for(int i=1;i<=n;i++)
        for(int j=i;j<=n;j++)
        {
            double ans=(double)i/(double)j;
            if(abs(ans-p)<dq)
            {
                dq=abs(ans-p);
                p1=i;p2=j;
            }
        }
        cout<<n<<" "<<p1<<"/"<<p2<<endl;
    }
}

输出:
1 1/1
2 1/2
3 2/3
4 2/3
5 3/5
6 3/5
7 3/5
8 5/8
9 5/8
10 5/8
11 5/8
12 5/8
13 8/13
14 8/13
15 8/13
16 8/13
17 8/13
18 8/13
19 8/13
20 8/13
可以得出规律来,找斐波那契数i小于等于n,并且i+1的斐波那契数>n;分子就等于i-1的斐波那契数,分母等于i的斐波那契数。
代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
unsigned long long n,fz,fm;
long long fb[1000];
int main()
{
    //freopen("DQSjangke.in","r",stdin);
    //freopen("DQSjangke.out","w",stdout);
    cin>>n;
    if(n==1)
        cout<<1<<"/"<<1;
    else 
    {
        fb[0]=0,fb[1]=1;
        for(int i=2;i<=93;i++)
            fb[i]=fb[i-1]+fb[i-2];
        for(int i=1;i<=93;i++)
        {
            if(fb[i]<=n&&fb[i+1]>n)
            {
                fz=fb[i-1];
                fm=fb[i];
            }
        }
        cout<<fz<<"/"<<fm;
    }

    //fclose(stdin);
    //fclose(stdout);
    return 0;
}

T2
Problem 2 惠及百姓的 DQS
题目描述
DQS 搬家啦!他来到了新房子里,却发现他的新家附近街区是不通水的。DQS 很恼怒,于是,他去规划局讨说法。规划局局长告诉他,通到他家附近只有一条管道,由于规划局的不作为,同时为了惠及百姓,DQS 主动担当起了为街区每户人家开入水口的任务。DQS 需要使得街区 n 座房子都可以有入水口。总水源只有一个出水口,显然不能使每家每户都接到水,这时,他发现了上古流传下来的神器——分离器。分离器是由一个进水口和 x 个出水口组成的,也就是说它可以使一个水管变成多个水管,现在 DQS 有每种类型的分离器各一个,分别是 2,3,……,k(分离器的型号代表它的出水
口有几个) 。由于规划局经费有限,所以 DQS 需要用最少的分离器联通所有房子。
输入描述
一行两个数,n 和 k,表示有 n 个住宅需要联通,k 种分离器(从 2 到 k
种)可供使用。
输出描述
一行一个整数,表示最少用几个分离器恰好联通所有房子,若不能联
通,则输出-1;
样例输入
Input1:4 3
Input2:5 5
Input3:8 4
样例输出
Output1: 2
Output2: 1
Output3: -1
数据范围及提示
对于 40%: 1 ≤ n ≤ 1000, 2 ≤ k ≤ 1000
对于 100% :1 ≤ n ≤ 10
18
, 2 ≤ k ≤ 10的9次方

题解:
需要自己推二分验证公式———–;二分用多少数量的管子最少,最优,特判1,和n<=m 的情况;
代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
long long n,m;
long long ans=0;
int main()
{
    //freopen("project.in","r",stdin);
    //freopen("project.out","w",stdout);
    scanf("%lld%lld",&n,&m);
    if(n==1)
    {
        cout<<"0";
        fclose(stdin);
        fclose(stdout);
        return 0;
    }
    if(m>=n)
    {
        printf("%d",1);
        fclose(stdin);
        fclose(stdout);
        return 0;
    }
    long long ans=m*(m-1);
    ans/=2;ans++;
    if(ans<n)
    puts("-1");
    else 
    {
        long long l=0,r=m-1,x;
        while (r-l>1)
        {
            x=(l+r)/2;
            ans=x*(2*m-3-x);
            ans/=2;
            if(ans+m>=n) r=x;
            else  l=x;
        }
        printf("%lld",r+1);
    }
    //fclose(stdin);
    //fclose(stdout);
    return 0;
}
//O(n)算法---虽然A不了.
/*long long dq=m;
    while (1)
    {
        if(dq==m)
        {
            n-=dq;
            dq--;
            ans++;
        }
        if(dq!=m)
        {
            n++;
            n-=dq;
            dq--;
            ans++;
        }
        if(n==0)
        {
            printf("%lld",ans);
            break;
        }
        if(n<0&&dq>=2)
        {
            printf("%lld",ans);
            break;
        }
        if(dq<2)
        {
            puts("-1");
            break;
        }
    }*/

Problem 3 DQS 真贪心
题目描述 DQS 的好朋友新开了一家礼品店,开业期间要 DQS 去给他撑场
子,显然,他会在 DQS 买礼品时给 DQS 一些便利。礼品店里
一共有 n 类礼物,第 i 类礼物的单价是 wi 元(买 k 个的花费
就是 wi*k 元) ,但是因为是 DQS,所以如果 DQS 买 x(x>0)
个 i 种礼品,老板会给他 ai*x+bi 个糖果,DQS 身上只带了 m
元,而 DQS 比较贪心,他希望用已有的这些钱得到最多的糖
果。
输入描述 第一行是 m 和 n,表示 DQS 拥有 m 元,礼品店中有 n 类礼品
接下来 n 行,每行有三个数,分别是 wi,ai,bi
输出描述 一个整数,输出能获得的最多糖果个数
样例输入 100 2
10 2 1
20 1 1
样例输出 21
数据范围及提示 对于 40%数据 n,m<=100
对于 60%数据 n,m<=500
对于 100%数据 n,m<=2000,0<=ai,bi<=2000,0<=wi<=2000
题解:可以先跑一边01背包,然后再跑一边完全背包问题解决;也可以直接跑一边完全背包(代码lc的)
01+完全:

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int w[3000],a[3000],b[3000];
int dp[3000];
int n,rmb;
int main()
{
    //freopen("candy.in","r",stdin);
    //freopen("candy.out","w",stdout);
    scanf("%d%d",&rmb,&n);
    for(int i=1;i<=n;i++)
    scanf("%d%d%d",&w[i],&a[i],&b[i]);
    for(int i=1;i<=n;i++)
    for(int j=rmb;j>=w[i];j--)
        dp[j]=max(dp[j],dp[j-w[i]]+a[i]+b[i]);  
    for(int i=1;i<=n;i++)
    for(int j=w[i];j<=rmb;j++)
        dp[j]=max(dp[j],dp[j-w[i]]+a[i]);
    printf("%d",dp[rmb]);
    fclose(stdin);
    fclose(stdout);
    return 0;
}

完全:

#include<iostream>
#include<cstdio>
using namespace std;
int dp[2005][2005];
int w[2005],a[2005],b[2005];
int main()
{
    freopen("candy.in","r",stdin);
    freopen("candy.out","w",stdout);
    int m,n;
    scanf("%d%d",&m,&n);
    for(int i=1;i<=n;i++)
        scanf("%d%d%d",&w[i],&a[i],&b[i]);
    for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
    {
        dp[i][j]=dp[i-1][j];
        if(j-w[i]>=0)
        {
            dp[i][j]=max(dp[i][j-w[i]]+a[i],dp[i][j]);
            dp[i][j]=max(dp[i-1][j-w[i]]+a[i]+b[i],dp[i][j]);
        }
    }
    printf("%d",dp[n][m]);
    fclose(stdin);
    fclose(stdout);
    return 0;
}

Problem 4 学 OI 的 DQS
题目描述 众所周知,DQS 是大学霸,可是他偏偏喜欢装弱! (他可是我们的
太阳啊) 。这天,他遇到了一个题目,可是他不想做。输入两个十
进制正整数 a 和 b,输出闭区间 [a ,b] 内 Round number 的个数 X
Round Number:把一个十进制数转换为一个无符号二进制数,该
进制数中 0 的个数大于等于 1 的个数。你能帮助他解决这个问题
输入描述 一行,2 个数。a,b;
输出描述 一行,X;
样例输入 2 12
样例输出 6
数据范围及提示 对于 40% 的数据, 保证 b-a <= 100000, a,b 属于 unsigned int;
对于 100% 的数据, 保证 b-a <= 2^60 a,b 属于 unsigned long long

题解:40分暴力滚粗了 233
代码:

#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
    freopen("Oierdqs.in","r",stdin);
    freopen("Oierdqs.out","w",stdout);
    long long a,b,tot=0;
    cin>>a>>b;
    while (a<=b)
    {
        int t=a,l;
        for(int i=1;i<=64;i++)
        {
            if(t%2==1) l=i;
            t/=2;
        }
        int ans=0;
        t=a;
        while (t!=0)
        {
            if(t%2==1) ans++;
            t/=2;
        }
        if((l-ans)>=(l+1)/2) tot++;
        a++;

    }
    cout<<tot;
}

第一季终于结束了,请看第二季。QAQ

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值