Codeforces Round #473 (Div. 2) D 数学,贪心 F 线性基,模板

D. Mahmoud and Ehab and another array construction task

题意:
给出一个数组 a[],要你构造出一个互质的字典序最小的数组 b[],且 b[] 的字典序要大于等于 a[] 。
tags:
预处理出 1e5 个素数,然后对于第 i 个数,它应该不包含前面 n-1 个数含有的质因子,满足这个条件后,我们贪心取最大的即可。且如果当前已经大于数组 a[] 了,那后面的就都贪心取最小的质数。

// CF 959D
#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a; i<=b; ++i)
#define per(i,b,a) for (int i=b; i>=a; --i)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define MP make_pair
#define PB push_back
#define fi  first
#define se  second
typedef long long ll;
const int N = 20000005;

const int M=2000005;  // M : size
bool mark[M];  // true : prime number
int pp[N], cnt;
void sieve_prime()
{
    memset(mark, true, sizeof(mark));
    mark[0] = mark[1] = false;
    for(int i=2; i<=sqrt(M); i++) {
        if(mark[i]) {
            for(int j=i*i; j<M; j+=i)
                mark[j]=false;
        }
    }
    rep(i,2,M-1) if(mark[i]) pp[++cnt] = i;
}

int n, a[N], b[N];
bool vis[M];
void get(int x) {
    for(int i=1; i<=cnt && pp[i]<=x; ++i) {
        while(x%pp[i]==0) vis[pp[i]]=true, x/=pp[i];
    }
}
bool is(int x) {
    for(int i=1; i<=cnt && pp[i]<=x; ++i)
        if(vis[pp[i]])
    {
        if(x%pp[i]==0) return false;
    }
    return true;
}
int main()
{
    sieve_prime();
    scanf("%d", &n);
    rep(i,1,n) scanf("%d", &a[i]);
    bool flag = false;
    int  ca = 1;
    rep(i,1,n)
    {
        if(flag) {
            for( ; vis[pp[ca]]; ++ca) ;
            vis[pp[ca]]=true;
            b[i] = pp[ca];
            continue;
        }
        if(i==1) b[1]=a[1], get(b[1]);
        else {
            for(int j=a[i]; ; ++j)
                if(is(j))
            {
                get(j);   b[i]=j;
                if(j>a[i]) flag = true;
                break;
            }
        }
    }
    rep(i,1,n) printf("%d ", b[i]);

    return 0;
}

F. Mahmoud and Ehab and yet another xor task

题意:
n 个数,q 个询问,每次询问有 l, x 。 询问前 l 个数里,有多少个子序列的异或和为 x 。
tags:
第一次见线性基的问题。。很有意思。
参考了博客 https://blog.csdn.net/qaq__qaq/article/details/53812883
我们把询问按 l 排序,对于每个询问我们把 a[1] ~ a[l] 都插入到线性基里。首先看线性基能否异或出 x ,然后看线性基里有几个数,如有 k 个数,那答案就是 2^(l-k) 。
可以这样考虑,如果线性基可以异或出 x ,线性基里有 k个数,那在另外 l - k 个数里取出一个数 y ,我们对于 y 取或不取有两种可能。如取 y ,那只要异或出 x 即可;如不取 y ,那就异或出 x^y 即可(肯定可以异或出 x^y 的,因为线性基的异或域和原序列的异或域相同)。

#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a; i<=b; ++i)
#define per(i,b,a) for (int i=b; i>=a; --i)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define MP make_pair
#define PB push_back
#define fi  first
#define se  second
typedef long long ll;
const int N = 200005, mod = 1e9+7;

ll  fpow(ll a, ll b) {
    ll ret = 1;
    for(a%=mod; b; b>>=1, a=a*a%mod) if(b&1) ret = ret*a%mod;
    return ret;
}

struct L_B
{
    long long d[61], p[61];
    int cnt;
    L_B() {
        memset(d,0,sizeof(d));
        memset(p,0,sizeof(p));
        cnt=0;
    }
    bool Insert(long long val) { //插入
        for (int i=60;i>=0;i--)
            if (val&(1LL<<i)) {
                if (!d[i]) { d[i]=val; break; }
                val ^= d[i];
            }
        return val>0;
    }
    bool is_in(long long val) { //存在性
        for(int i=60; i>=0; --i) {
            if(val&(1LL<<i)) {
                if(d[i]) val ^= d[i];
            }
        }
        return val==0;
    }
    long long query_max() { //最大值
        long long ret=0;
        for (int i=60;i>=0;i--)
            if ((ret^d[i])>ret)
                ret^=d[i];
        return ret;
    }
    long long query_min() { //最小值
        for (int i=0;i<=60;i++)
            if (d[i]) return d[i];
        return 0;
    }
    void rebuild() {  //求 k 小值前加
        for (int i=60;i>=0;i--)
            for (int j=i-1;j>=0;j--)
                if (d[i]&(1LL<<j))
                    d[i]^=d[j];
        for (int i=0;i<=60;i++)
            if (d[i]) p[cnt++]=d[i];
    }
    long long kthquery(long long k) { //k小值
        long long ret=0;
        if (k>=(1LL<<cnt))
            return -1;
        for (int i=60;i>=0;i--)
            if (k&(1LL<<i))
                ret^=p[i];
        return ret;
    }
} LB;
L_B merge(const L_B &n1,const L_B &n2) //合并
{
    L_B ret=n1;
    for (int i=60;i>=0;i--)
        if (n2.d[i])
            ret.Insert(n2.d[i]);
    return ret;
}

int a[N];
ll  ans[N];
pair< int, pair< int , int >  > Q[N];
int main()
{
    int n, q;  scanf("%d%d", &n, &q);
    rep(i,1,n) scanf("%d", &a[i]);
    rep(i,1,q) scanf("%d%d", &Q[i].fi, &Q[i].se.fi), Q[i].se.se=i;
    sort(Q+1, Q+1+q);
    int now = 1;
    rep(i,1,q)
    {
        for( ; now<=Q[i].fi; ++now) LB.Insert(a[now]);
        if(!LB.is_in(Q[i].se.fi)) {
            ans[Q[i].se.se] = 0;
            continue;
        }
        int cnt = 0;
        per(j,60,0) if(LB.d[j]) ++cnt;
        ans[Q[i].se.se] = fpow(1LL*2, Q[i].fi-cnt);
    }
    rep(i,1,q) printf("%lld\n", (ans[i]+mod)%mod);

    return 0;
}
posted @ 2018-04-13 15:48  v9fly  阅读(193)  评论(0编辑  收藏  举报