P6104 [EER2]相同的数字

题目

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
#define N 100010
const int M=1<<17,P=1e7+20;
int n,q,t,c1,c2,m;
int a[N];
int v[P],f[P];
vector<long long>vec,c[2],e[2];
long long g[2],ans;
inline void add(int o,int x,int k){
    if(!x) return ;
    if((int)c[o].size()<x+1) c[o].resize(x+1);//扩充vector
    c[o][x]+=k;//第o情况 间距x的情况加1
}
//f[i]为i之前有多少个质数
inline void prework(int o,int m){
    vector<int>d(vec.size());
    for (int i = 1; i <= n; ++i) {//首尾加入答案
        int x = a[i];
        if (v[x] == v[m]) add(o, m - x, 1);
        else {
            //vec[f[v[m]]-1]结尾的上一个质数
            add(o, v[x] - x, 1);
            if (m == v[m]) add(o, m - vec[f[v[m]]-1], 1);//
            else g[o] += m - vec[f[v[m]]-1];//要跳那么多步
            ++d[f[v[x]]];
        }
    }
    for (int i = 0; vec[i+1] < v[m]; ++i) {//差分 并计算每个点之前的点的总数
        if (i) d[i] += d[i-1];
        add(o, vec[i+1] - vec[i], d[i]);
    }
    e[o].resize(c[o].size());
    for (int i = 0; i < c[o].size(); ++i) {//前缀和处理
        e[o][i] = c[o][i] * i;
        if (i) e[o][i] += e[o][i-1], c[o][i] += c[o][i-1];
    }
}

inline long long solve(int o) {
    //c2/c1为允许的长度
    int k = min((int)1.0 * c2 / c1, (int)c[o].size() - 1);//k为最大长度
    return (e[o][k] + g[o]) * c1 + (c[o].back() - c[o][k]) * c2;//走的步数加跳的步数
}




int main()
{
    //预处理质数
    ios::sync_with_stdio(false);
    cin.tie(0);
    for(int i=2;i<P;i++){
        if(!v[i]) vec.push_back(v[i]=i),f[i]=vec.size()-1;
        for(int j=0;j<vec.size()&&i*vec[j]<P;j++) {
            v[i * vec[j]] = 1;
            if(i%vec[j]==0)
                break;
        }
    }
    for(int i=P-1;i;i--)
        if(v[i]!=i) v[i]=v[i+1];


    cin>>n>>q>>t;
    for(int i=1;i<=n;i++) cin>>a[i],m=max(m,a[i]);
    sort(a+1,a+1+n);
    //预处理到m和到v[m]的情况
    prework(0,m);prework(1,v[m]);
    for (int i=1;i<=q;++i) {
        cin>>c1>>c2,c1^=t*ans, c2^=t*ans;
        cout<<(ans = min(solve(0), solve(1)))<<endl;
        ans%=M;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值