2017.7.22小测

7.22test

NOIP2016 模拟赛
             ——那些年,我们学过的文化课

     啧啧,虽然是怀着不爆零的心思去考的试,不过这分说实话也是有点丑了⊙﹏⊙

  不过没事,每一次考试都是一次教训,希望下次能够考得稍微好点吧嘻嘻

加油吧~

T1

1.背单词
(word.c/cpp/pas)
【题目描述】
fqk 退役后开始补习文化课啦, 于是他打开了英语必修一开始背单词。 看着满篇的单词非常头疼, 而每次按照相同的顺序背效果并不好,于是 fqk 想了一种背单词的好方法!他把单词抄写到一个 n 行 m 列的表格里,然后每天背一行或者背一列。他的复习计划一共有 k 天,在k 天后, fqk 想知道,这个表格中的每个单词,最后一次背是在哪一天呢?
【输入格式】
第一行三个整数 k m n , , 。
接下来 k 行,每行的格式可能如下:
1。r ,表示当前天 fqk 背了第 r 行的单词。
 2。c ,表示当前天 fqk 背了第 c 列的单词。
【输出格式】
输出包含 n 行, 每行 m 个整数, 表示每个格子中的单词最后一次背是在哪天,如果这个单词没有背过,则输出 0 。
【输入样例】
3 3 3
1 2
2 3
1 3
【输出样例】
0 0 2
1 1 2
3 3 3
【数据范围】
对于 % 30 的数据, 1000 , ,  k m n 。
对于 % 100 的数据, 100000 , 100000 , 5000 ,     k m n m n 。
【时空限制】
对于每个测试点,时间限制为 s 1 ,空间限制为 MB 512 。

思路:

  这题可以直接打暴力的w,只需要在输入的数据里面判断一下是行还是列即可

坑点:

  记住要输出比较靠后的那个

上代码:

  1)我敲的是特别裸的暴力,纯暴力,无脑暴力

  这样都50.。。。

  厉害了(秘技——傻逼暴力!!!):

#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
using namespace std;

const int N = 5050;
const int M = 5050;
int n,m,k;//n 行 m 列 
int r[N],c[M];

inline int reads()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0' || ch>'9')
    {if(ch=='-') f=-1;ch=getchar();}
    while(ch>='0' && ch<='9')
    {x=10*x+ch-'0';ch=getchar();}
    return x*f;
}

int main()
{
    freopen("word.in","r",stdin);
    freopen("word.out","w",stdout);
//    scanf("%d%d%d",&n,&m,&k);
    n=reads(),m=reads(),k=reads();
    for(int i=1,nu,b;i<=k;++i)
    {
//        scanf("%d%d",&nu,&b);
        nu=reads(),b=reads();
        if(nu==1)
            r[b]=i;
        else
            c[b]=i;
    }
    for(int i=1;i<=n;++i)
    {
        for(int j=1;j<=m;++j)
            if(r[i]>c[j])
                printf("%d ",r[i]);
            else
                printf("%d ",c[j]);
        printf("\n");
    }
    return 0;
}

  2)正解

#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
#include <ctime>
using namespace std;

const int N = 5050;
const int M = 5050;
int n,m,k;//n 行 m 列 
int r[N],c[M];

inline int reads()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0' || ch>'9')
    {if(ch=='-') f=-1;ch=getchar();}
    while(ch>='0' && ch<='9')
    {x=10*x+ch-'0';ch=getchar();}
    return x*f;
}

int main()
{
    freopen("word.in","r",stdin);
    freopen("word.out","w",stdout);
//    scanf("%d%d%d",&n,&m,&k);
    n=reads(),m=reads(),k=reads();
    for(int i=1,nu,b;i<=k;++i)
    {
//        scanf("%d%d",&nu,&b);
        nu=reads(),b=reads();
        if(nu==1)
            r[b]=i;
        else
            c[b]=i;
    }
    for(int i=1;i<=n;++i)
    {
        for(int j=1;j<=m;++j)
            if(r[i]>c[j])
                printf("%d ",r[i]);
            else
                printf("%d ",c[j]);
        printf("\n");
    }
    return 0;
}  

 


T2

2.脱水缩合
(merge.c/cpp/pas)
【题目描述】
fqk 退役后开始补习文化课啦, 于是他打开了生物必修一开始复习蛋白质,他回想起了氨基酸通过脱水缩合生成肽键,具体来说,一个氨基和一个羧基会脱去一个水变成一个肽键。于是他脑洞大开,给你出了这样一道题:
fqk 将给你 6 种氨基酸和 m 个脱水缩合的规则,氨基酸用
' a' , ' b' , 'c ' , 'd ' , 'e ' , 'f '表示,每个规则将给出两个字符串 t s, ,其中|t |=1 ,  |s |=2  ,表示 s 代表的两个氨基酸可以通过脱水缩合变成 t 。然后请你构建一个长度为 n ,且仅由 ' a' , ' b' , 'c ' , 'd ' , 'e ' , 'f ' 构成的氨基酸序列,如果这个序列的前两个氨基酸可以进行任意一种脱水缩合, 那么就可以脱水缩合,脱水缩合后序列的长度将 1  ,这样如果可以进行 1  n 次脱水缩合,最终序列的长度将变为 1 ,我们可以认为这是一个蛋白质,如果最后的蛋白质为 ' 'a , 那么初始的序列就被称为一个好的氨基酸序列。 fqk 想让你求出有多少好的氨基酸序列。
注:题目描述可能与生物学知识有部分偏差(即氨基酸进行脱水缩合后应该是肽链而不是新的氨基酸),请以题目描述为准。
【输入格式】
第一行两个整数 q n, 。
接下来 q 行,每行两个字符串 t s, ,表示一个脱水缩合的规则。
【输出格式】
一行,一个整数表示有多少好的氨基酸序列。
【输入样例】
3 5
ab a
cc c
ca a
ee c
ff d
【输出样例】
4
【样例解释】
一共有四种好的氨基酸序列,其脱水缩合过程如下:
"abb" "ab" "a"
"cab" "ab" "a"
"cca" "ca" "a"
"eea" "ca" "a"
【数据范围】
对于 % 100 的数据, 36 , 6 2    q n 。数据存在梯度。
【时空限制】
对于每个测试点,时间限制为 2s ,空间限制为 512 MB 

思路:

  先找组成的字符串,然后判断是否能够变幻出来,如果可以,ans++,这样就避免了重复的情况。

坑点:

  进行覆盖的时候只需要覆盖一个位置即可,回溯也只需要回溯被修改的位置,其他保持不变

教训:

  不会的东西就别去乱搞,比如set

上代码:

1)瞎鸡巴乱搞233(就搞了20qwq)

 

#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
#include <set>
using namespace std;

const int Q = 50;
int n,q,ans;
int ru[7];
bool vis[27];
set<string>orz;

struct B {
    string u;
    char v; 
}e[Q];

inline int reads()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0' || ch>'9')
    {if(ch=='-') f=-1;ch=getchar();}
    while(ch>='0' && ch<='9')
    {x=10*x+ch-'0';ch=getchar();}
    return x*f;
}

void dfs(string noww,char f,int nowl,bool flag)
{
    if(nowl==n)
    {
        orz.insert(noww);
        return;
    }
    int rp,cp;
    for(int i=1;i<=q;++i)
    {
        if(e[i].v==f)
        {
            char pre=e[i].u[0],nxt=e[i].u[1];
            rp=pre-96,cp=nxt-96;
            ///you 
            if(flag)
            {
                int len=noww.length();
                char tmp[8];
                tmp[0]=e[i].u[0],tmp[1]=e[i].u[1];
                for(int j=0;j<len;++j)
                    tmp[j+len]=noww[j+1];
                noww=tmp;
                if(ru[rp])
                    dfs(noww,pre,nowl+1,0);
                if(ru[cp])
                    dfs(noww,nxt,nowl+1,1);
            }
            ///zuo 
            else
            {
                int len=noww.length();
                char tmp[8];
                for(int j=0;j<len-1;++j)
                    tmp[j]=noww[j];
                tmp[len]=e[i].u[0],tmp[len+1]=e[i].u[1];
                noww=tmp;
                if(ru[rp])
                    dfs(noww,pre,nowl+1,0);
                if(ru[cp])
                    dfs(noww,nxt,nowl+1,1);
            }
        }
    }
}

int main()
{
    freopen("merge.in","r",stdin);
    freopen("merge.out","w",stdout);
//    scanf("%d%d",&n,&q);
    n=reads(),q=reads();
    for(int i=1,x;i<=q;++i)
    {
        cin>>e[i].u>>e[i].v;
        x=e[i].v-96;
        ru[x]++;
        if(x==1)
            ans++;
    }
    if(!ans || n==1)
    {
        printf("0\n");
        return 0;
    }
    for(int i=1;i<=q;++i)
    {
        if(e[i].v=='a')
        {
            dfs(e[i].u,e[i].u[0],2,0);
            dfs(e[i].u,e[i].u[1],2,1);
        }
    }
    printf("%d\n",orz.size());
    return 0;
}

2)正解

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;

const int K = 50;
char s[K][3],t[K][3];
char a[8];
int n,q,ans;
bool vis[K];

bool judge(int x)
{
    //成功构造出一个 
    if(x==n && a[n]=='a')
        return true;
    for(int i=1;i<=q;++i)
        //若能够进行转化 
        if(s[i][1]==a[x] && s[i][2]==a[x+1])
        {
            int tmp=a[x+1];
            //进行覆盖 
            a[x+1]=t[i][1];
            bool flag=judge(x+1);
            //回溯,多寻找几组可行方案 
            a[x+1]=tmp;
            //若成功,return 
            if(flag)
                return true;
        }
    return false;
}

void dfs(int x)
{
    if(x==n+1)
    {
        if(judge(1))
            ans++;
        return;
    }
    for(int i=0;i<6;++i)
    {
        a[x]=i+'a';
        dfs(x+1);
    }
}

int main()
{
    freopen("merge.in","r",stdin);
    freopen("merge.out","w",stdout);
    scanf("%d%d",&n,&q);
    for(int i=1;i<=q;++i)
    {
        scanf("%s",s[i]+1);
        scanf("%s",t[i]+1);
    }
    dfs(1);
    cout<<ans;
    return 0;
}

 


T3

3.一次函数
(fx.c/cpp/pas)
【题目描述】
fqk 退役后开始补习文化课啦, 于是他打开了数学必修一开始复习函数, 他回想起了一次函数都是 f(x)=kx+b 的形式, 现在他给了你 n 个一次函数 fi(x)=kix+bi 然后将给你 m 个操作, 操作将以如下格式给出:

M . 1 i k b ,把第 i 个函数改为 fi(x)=kx+b。

Q . 2 l r x ,询问fr(fr-1(...fl(x)))mod 1000000007 的值。
【输入格式】
第一行两个整数 n , m ,代表一次函数的数量和操作的数量。
接下来 n 行,每行两个整数,表示k,bi 。
接下来 m 行,每行的格式为 M i k b 或 Q l r x 。
【输出格式】
对于每个操作 Q ,输出一行表示答案。
【输入样例】
5 5
4 2
3 6
5 7
2 6
7 5
Q 1 5 1
Q 3 3 2
M 3 10 6
Q 1 4 3
Q 3 4 4
【输出样例】
1825
17
978
98
【数据范围】
对于 % 30 的数据, n,m<=1000 ,。
对于 % 100 的数据, n,m<=200000,k b,x<1000000007
【时空限制】
对于每个测试点,时间限制为 2s ,空间限制为 512MB

思路:

  1)考场上想到了线段树,但是因为懒不想敲,拼命的去想第二个,结果俩题都炸掉了。。。

  2)正解就是线段树

上代码:

  1)我考场上写的就不需要贴出来啦~\(≧▽≦)/~毕竟不好看还没分

(雾

  2)正解:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#define LL long long
#define lson root<<1
#define rson root<<1|1
using namespace std;

const int N = 200005;
const int Mod = 1000000007;
int n,m,k[N],b[N];

struct C {
    int l,r;
    LL mul,sum;
}t[N<<2];

inline int reads()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0' || ch>'9')
    {if(ch=='-') f=-1;ch=getchar();}
    while(ch>='0' && ch<='9')
    {x=10*x+ch-'0';ch=getchar();}
    return x*f;
}

inline C unions(C le,C ri)
{
    C ret;
    ret.l=le.l,ret.r=ri.r;
    ret.mul=le.mul*ri.mul%Mod;
    ret.sum=(le.sum*ri.mul%Mod+ri.sum)%Mod;
    return ret;
}

inline void update(int root)
{
    t[root]=unions(t[lson],t[rson]);
}

inline void build(int root,int l,int r)
{
    if(l==r)
    {
        t[root].l=t[root].r=l;
        t[root].sum=b[l];
        t[root].mul=k[l];
        return;
    }
    int mid=(l+r)>>1;
    build(lson,l,mid);
    build(rson,mid+1,r);
    update(root);
}

inline void modify(int root,int x,int ki,int bi)
{
    int l=t[root].l,r=t[root].r;
    if(l==r)
    {
        t[root].sum=bi;
        t[root].mul=ki;
        return;
    }
    int mid=(l+r)>>1;
    if(x<=mid)
        modify(lson,x,ki,bi);
    else
        modify(rson,x,ki,bi);
    update(root);
}

inline C query(int root,int l,int r)
{
    int ll=t[root].l,rr=t[root].r;
    if(ll==l && rr==r)
        return t[root];
    int mid=(ll+rr)>>1;
    if(r<=mid)
        return query(lson,l,r);
    else
    if(l>mid)
        return query(rson,l,r);
    else
        return unions(query(lson,l,mid),query(rson,mid+1,r));
}

int main()
{
    freopen("fx.in","r",stdin);
    freopen("fx.out","w",stdout);
    n=reads(),m=reads();
    for(int i=1;i<=n;++i)
        k[i]=reads(),b[i]=reads();
    build(1,1,n); 
    for(int i=1;i<=m;++i)
    {
        char w[5];
        cin>>w;
        if(w[0]=='M')
        {
            int x=reads(),ki=reads(),bi=reads();
            modify(1,x,ki,bi);
        }
        else
        {
            int l=reads(),r=reads(),x=reads();
            C ans=query(1,l,r);
            printf("%I64d\n",(ans.mul*x%Mod+ans.sum)%Mod);
        }
    }
    return 0;
}

 

posted @ 2017-07-22 20:44  夜雨声不烦  阅读(269)  评论(0编辑  收藏  举报