2018.8.11提高B组模拟考试

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

T1 题目简述:jzoj5456

   解题思路:大水题。

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

             先把人按身高从高到低排序,然后依次插入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

   解题思路:大水题。

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

#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

   解题思路:大水题+无F♂A可说的题。

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

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

             解法二:Trie树。

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

             至于为什么说无F♂A可说是因为题解中对于解法一给了一个式子,大概意思就是:

             模数取10^9时,只有0.67%的概率正确。

             模数取10^10时,有60.65%的概率正确。

             模数取10^12时,有99.61%的概率正确。

             您取一个10^15~10^16大小的模数就能保证正确了。

             我:???(顺带一提,我的模数是10^8级别的)

#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;
}

猜你喜欢

转载自www.cnblogs.com/water-radish/p/9459901.html