2018.8.11提高B组模拟考试

今天的题目水到连出题人都懒得讲了。

 

T1 题目简述:jzoj5456

 

Description

nodgd的粉丝太多了,每天都会有很多人排队要签名。
今天有𝑛个人排队,每个人的身高都是一个整数,且互不相同。很不巧,nodgd今天去忙别的事情去了,就只好让这些粉丝们明天再来。同时nodgd提出了一个要求,每个人都要记住自己前面与多少个比自己高的人,以便于明天恢复到今天的顺序。
但是,粉丝们或多或少都是有些失望的,失望使她们晕头转向、神魂颠倒,已经分不清楚哪一边是“前面”了,于是她们可能是记住了前面比自己高的人的个数,也可能是记住了后面比自己高的人的个数,而且他们不知道自己记住的是哪一个方向。
nodgd觉得,即使这样明天也能恢复出一个排队顺序,使得任意一个人的两个方向中至少有一个方向上的比他高的人数和他记住的数字相同。可惜𝑛比较大,显然需要写个程序来解决,nodgd很忙,写程序这种事情就交给你了。

Input

第一行输入一个整数𝑛,表示指令的条数。
接下来𝑛行,每行两个整数𝑎𝑖,𝑏𝑖,表示一个人的身高和她记住的数字,保证身高互不相同。

Output

输出一行,这个队列里从前到后的每个人的身高。如果有多个答案满足题意,输出字典序最小。如果不存在满足题意的排列,输出“impossible”(不含引号)。

Data Constraint

n<=100000
ai<=10^9

 

   解题思路:大水题。

             贪心。由于题目要求字典序最小,因此要保证身高越低的排名越靠前。

             先把人按身高从高到低排序,然后依次插入vector。

             这样可以保证在身高为a[i]的人插入vector前vector内的人身高都大于a[i]。

             要保证当前这个人排名最靠前,只需对(他的要求)和(比他身高高的人数-他的要求)取min,

             再插入vector的第(min+1)个位置即可。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<vector>
#include<utility>
using namespace std;
int n;
struct uio{
    int hei,ask;
}peo[100001];
vector<int> vec;
bool cmp(uio x,uio y)
{
    return x.hei>y.hei;
}
int main()
{
    freopen("queue.in","r",stdin);
    freopen("queue.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d%d",&peo[i].hei,&peo[i].ask);
    sort(peo+1,peo+1+n,cmp);
    for(int i=1;i<=n;i++)
    {
        int tmp=min(peo[i].ask,i-1-peo[i].ask);
        if(tmp<0) {printf("impossible\n");return 0;}
        vec.insert(vec.begin()+tmp,peo[i].hei);
    }
    for(int i=0;i<vec.size();i++)
        printf("%d ",vec[i]);
    return 0;
}

 


 

T2 题意简述:jzoj5458

 

Description

小X 是一位热爱数学的男孩子,在茫茫的数字中,他对质数更有一种独特的情感。小X 认为,质数是一切自然数起源的地方。
在小X 的认知里,质数是除了本身和1 以外,没有其他因数的数字。
但由于小X 对质数的热爱超乎寻常,所以小X 同样喜欢那些虽然不是质数,但却是由两个质数相乘得来的数。
于是,我们定义,一个数是小X 喜欢的数,当且仅当其是一个质数,或是两个质数的乘积。
而现在,小X 想要知道,在L 到R 之间,有多少数是他喜欢的数呢?

Input

第一行输入一个正整数Q,表示询问的组数。
接下来Q 行。包含两个正整数L 和R。保证L≤R。

Output

输出Q 行,每行一个整数,表示小X 喜欢的数的个数。

Data Constraint

 

   解题思路:大水题。

             线性筛的同时顺便记录满足要求的数的个数,再顺便求一下前缀和就行了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#define ll long long
using namespace std;
ll n,cnt,pri[10000001],num[10000001],jdg[10000001];
void getnum()
{
    for(ll i=2;i<=10000000;i++)
    {
        if(jdg[i]==0) pri[++cnt]=i,num[i]=1;
        num[i]+=num[i-1];
        for(ll j=1;j<=cnt;j++)
        {
            if(pri[j]*i>10000000) break;
            if(!jdg[i]) num[pri[j]*i]=1;
            jdg[i*pri[j]]=1;
            if(!(i%pri[j])) break;
        }
    }
}
int main()
{
    freopen("prime.in","r",stdin);
    freopen("prime.out","w",stdout);
    getnum();
    scanf("%lld",&n);
    for(ll i=1;i<=n;i++)
    {
        ll u,v;
        scanf("%lld%lld",&u,&v);
        printf("%lld\n",num[v]-num[u-1]);
    }
    return 0;
}

 


 

T3 题意简述:jzoj5462

 

Description

nodgd写了一篇文章,自认为这是一篇好文章。nodgd的文章由𝑛个小写英文字母组成。文章的一个子串指的是文章中的一段连续的字母,子串的长度就是这一段的字母个数。nodgd在文章中用了排比、对偶、前后照应之类的手法,所以就有很多个子串是相同或者相近的。为了向大家证明这是一篇好文章,nodgd决定给自己的文章进行评分。nodgd首先确定了一个整数𝑚,然后统计出文章中有多少个不相同的长度为𝑚的子串,这个数量就是文章的评分。
然而,nodgd懒得老老实实计算这个评分了,就把任务丢给了你。

Input

第一行包含两个整数𝑛,𝑚,表示文章的长度和需要统计的子串长度。
第二行包含一个长度为𝑛的只包含小写字母的字符串。

Output

输出一行一个整数,表示文章的评分。

Data Constraint

对于30%的数据,1≤𝑚≤𝑛≤200;
对于50%的数据,1≤𝑚≤𝑛≤2000;
对于另外20%的数据,1≤𝑚≤50≤𝑛≤200000;
对于100%的数据,1≤𝑚≤𝑛≤200000。

 

   解题思路:大水题。

             正解写了一大堆奇奇怪怪的东西,其实根本没有那么麻烦。

             解法一:Hash,也就是本代码描述的算法。

             解法二:Trie树。

             解法三:后缀自动机。 <-- ErkkiErkko大佬强力推荐

             以下代码采用了最菜的第一种思路。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#define MOD 383109303154469
#define base 233
#define ll long long
using namespace std;
ll n,m,ans=1,num[200001],bpow;
char a[200001];
int main()
{
    freopen("article.in","r",stdin);
    freopen("article.out","w",stdout);
    scanf("%lld%lld",&n,&m);
    scanf("%s",a+1);
    bpow=1;
    for(ll i=1;i<m;i++) bpow=bpow*base%MOD;
    for(ll i=1;i<=m;i++) num[1]=(num[1]*base+a[i])%MOD;
    for(ll i=m+1;i<=n;i++)
        num[i-m+1]=((num[i-m]-bpow*a[i-m]%MOD+MOD)*base+a[i])%MOD;
//    for(int i=1;i<=n-m+1;i++)
//        for(int j=i;j<=i+m-1;j++)
//            num[i]=(num[i]*base+a[j])%MOD;
    sort(num+1,num+1+n-m+1);
//    for(ll i=1;i<=n-m+1;i++) printf("%lld\n",num[i]);
    for(ll i=2;i<=n-m+1;i++) if(num[i]!=num[i-1]) ans++;
    printf("%lld\n",ans);
    return 0;
}

 

posted @ 2018-08-11 15:25  radishえらい  阅读(242)  评论(0编辑  收藏  举报