Comet OJ - Contest #8题解

传送门

\(A\)

咕咕咕

const int N=1005;
char s[N][N];int len[N],n,id;
inline bool cmp(R int j,R int k){
    R int l=min(len[j],len[k]);
    fp(i,1,l)if(s[j][i]!=s[k][i])return s[j][i]<s[k][i];
    return len[j]<len[k];
}
int main(){
    scanf("%d",&n),id=1;
    fp(i,1,n)scanf("%s",s[i]+1),len[i]=strlen(s[i]+1);
    fp(i,1,n)if(cmp(i,id))id=i;
    printf("%s\n",s[id]+1);
    return 0;
}

\(B\)

咕咕

const int N=1e5+5;
typedef long long ll;
int a[N],n;ll sum,sp,res;
int main(){
    scanf("%d",&n);
    fp(i,1,n)scanf("%d",&a[i]),sum+=a[i],sp+=1ll*a[i]*a[i];
    fp(i,1,n)printf("%lld ",sp+1ll*n*a[i]*a[i]-(sum*a[i]<<1));
    return 0;
}

\(C\)

首先把所有的\(p_i=b_{i}\times a_{i+1}\)给取出来,并令\(sum=\sum p_i\),那么如果对于一个区间\([l,r]\)执行操作,答案就是\(sum+(k-1)p_{l}+(k-1)p_{r+1}+(k^2-1)(\sum_{i=l+1}^{r}p_i)\)

那么我们枚举\(r\),并把后面那个东西拆成前缀和相减的形式,记录下使值最小的\(l\)对应的值即可

typedef long long ll;
const int N=1e5+5;
int a[N],b[N],p[N],n,k;ll sum[N],res,mn,pmn;
int main(){
    scanf("%d%d",&n,&k);
    fp(i,1,n)scanf("%d%d",&a[i],&b[i]);
    fp(i,1,n+1)p[i]=b[i-1]*a[i];
    fp(i,1,n+1){
        sum[i]=sum[i-1]+p[i]*(k*k-1);
        cmin(mn,pmn+sum[i-1]+p[i]*(k-1));
        cmin(pmn,-sum[i]+p[i]*(k-1));
    }
    fp(i,1,n+1)mn+=p[i];
    printf("%lld\n",mn);
    return 0;
}

\(D\)

我是白痴……

对于每一个\(i\),记录一个\(mn_i\)表示左边最大能选多少和\(mx_i\)表示右边最多能选多少,那么如果一个询问\([l,r]\)满足\(l\in [mn_i,i]\)且\(r\in [i,mx_i]\),那么\(a_i\)就会对这个询问有贡献

这就是个二维偏序问题了,离线之后可以变成一维,用树状数组维护即可

//quming
#include<bits/stdc++.h>
#define R register
#define pb push_back
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
int read(){
    R int res,f=1;R char ch;
    while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
    for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
    return res*f;
}
typedef long long ll;
const int N=1e6+5;
struct node{
    int u,v,w;
    inline node(R int uu,R int vv,R int ww):u(uu),v(vv),w(ww){}
};
vector<node>p[N];int c[N],a[N],id[N],l[N],r[N],op[N],tid[N],ans[N],mn[N],mx[N];
int n,m,q,top,sum;ll res;
inline void add(R int x,R int y){for(;x<=n;x+=x&-x)c[x]+=y;}
inline int query(R int x){R int res=0;for(;x;x-=x&-x)res+=c[x];return res;}
inline bool cmp(const int &x,const int &y){return r[x]<r[y];}
int main(){
//  freopen("testdata.in","r",stdin);
    n=read(),m=read(),q=read();
    fp(i,1,n)a[i]=read(),mn[i]=1,mx[i]=n;
    for(R int i=1,u,v;i<=m;++i){
        u=read(),v=read();
        u<v?cmin(mx[u],v-1):cmax(mn[u],v+1);
    }
    fp(i,1,n)p[i].pb(node(mn[i],i,a[i])),p[mx[i]+1].pb(node(mn[i],i,-a[i]));
    fp(i,1,q)id[i]=i,l[i]=read(),r[i]=read();
    sort(id+1,id+1+q,cmp);
    for(R int i=1,j=1;i<=q;++i){
        while(j<=n&&j<=r[id[i]]){
            for(auto x:p[j])add(x.u,x.w),add(x.v+1,-x.w);
            ++j;
        }
        ans[id[i]]=query(l[id[i]]);
    }
    fp(i,1,q)res^=1ll*i*ans[i];
    printf("%lld\n",res);
    return 0;
}

\(E\)

不难发现,设\(x\)中质因子\(p_i\)的次数是\(c_i\),则\(f(x)\)中质因子\(p_i\)的次数是\(\left\lfloor{c_i\over 2}\right\rfloor\)(即每一个质因子的次数都是向下取整)

那么我们枚举\(f(x)\),答案就是\(\sum_{i=1}^{\sqrt{n}} i\times g(n/{i^2})\),其中\(g(n)\)表示\(1\)到\(n\)中最多只有一个质因子的数的个数,也就是\(\sum_{i=1}^n \mu^2(i)\)

计算\(g(n)\)的时候,我们可以用\(\mu\)来容斥,所以\(g(n)=\sum_{i=1}^{\sqrt(n)}\mu(i){n\over {i^2}}\)

这两个东西都可以用整除分块优化,而且\({n\over {i^2}}\)的不同个数是\(O(n^{1\over 3})\)个,所以复杂度是有保证的

//quming
#include<bits/stdc++.h>
#define R register
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
#define gg(u) for(int &i=cur[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
typedef long long ll;
const int N=1e7+5;
bitset<N>vis;int p[N],mu[N],sm[N],m;
void init(int n=1e7){
    mu[1]=1;
    fp(i,2,n){
        if(!vis[i])p[++m]=i,mu[i]=-1;
        for(R int j=1;j<=m&&1ll*i*p[j]<=n;++j){
            vis[i*p[j]]=1;
            if(i%p[j]==0)break;
            mu[i*p[j]]=-mu[i];
        }
    }
    fp(i,1,n)sm[i]=sm[i-1]+(mu[i]<0?-mu[i]:mu[i]);
    fp(i,1,n)mu[i]+=mu[i-1];
}
ll res=0,bin[25],n,t;int T;
inline ll calc(R ll n){
    if(n<=1e7)return sm[n];
    R ll t=sqrt(n),res=0;
    for(R ll l=1,r;l<=t;l=r+1)
        r=sqrt(n/(n/(l*l))),res+=n/(l*l)*(mu[r]-mu[l-1]);
    return res;
}
int main(){
//  freopen("testdata.in","r",stdin);
    init();
    for(scanf("%d",&T);T;--T){
        scanf("%lld",&n),res=0;
        t=sqrt(n);
        for(R ll l=1,r;l<=t;l=r+1)
            r=sqrt(n/(n/(l*l))),res+=calc(n/(l*l))*(r-l+1)*(l+r)>>1;
        printf("%lld\n",res);
    }
    return 0;
}

\(F\)题咕了

原文地址:https://www.cnblogs.com/yuanquming/p/11335803.html

时间: 2024-08-30 17:06:05

Comet OJ - Contest #8题解的相关文章

Comet OJ - Contest #15题解

A 双十一特惠 (简单版) n  <=  1e19,   1e9 > 1(8) https://www.cometoj.com/contest/79/problem/A?problem_id=4198 #include<bits/stdc++.h> using namespace std; int main(){ int t; cin >> t; while(t--) { int cnt1 = 0; int n;cin >> n; int pr[] = {1

Comet OJ - Contest #14题解

Contest14的本质:区间覆盖+Tarjan( A 把距离公式两边平方即可 注意要long long code #include <algorithm> #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #define fo(a,b,c) for (a=b; a<=c; a++) #define fd(a,b,c) for (a=b;

Comet OJ - Contest #5

Comet OJ - Contest #5 总有一天,我会拿掉给\(dyj\)的小裙子的. A 显然 \(ans = min(cnt_1/3,cnt_4/2,cnt5)\) B 我们可以感性理解一下,最大的满足条件的\(x\)不会太大 因为当\(x\)越来越大时\(f(x)\)的增长速度比\(x\)的增长速度慢得多 其实可以证明,最大的满足的\(x\)不会超过\(100\) 因为没有任何一个三位数的各位之和大于等于\(50\) 所以我们就直接预处理\(1-99\)所有的合法的 暴力枚举即可 其实

符文能量(Comet OJ - Contest #8)

给Comet OJ打个小广告,挺好用的,比较简洁,给人感觉很好用 Contest #8是我打的第一场本oj比赛,很遗憾A了前两道傻逼题就没思路了,然后就不打算打了....... https://www.cometoj.com/contest/58/problem/C?problem_id=2760 怎么做啊完全不会啊我那么菜,虽然看到是dp但嫌太麻烦就放弃了: 靠后仔细想了想原来这道题很简单: 结构体node e[];储存ai,bi值(当然你用数组我也不拦着),因为合并的方式很特殊,可以不管合并

Comet OJ - Contest #10 B

Comet OJ - Contest #10 B 沉鱼落雁 思维题 题意 : 每个数字最多重复出现三次,有n给数字,让你尽可能的使得相同数字之间的最小距离尽可能大 思路 :分三种情况套路 设 a b c 分别代表出现 一次, 两次, 三次 数字的个数 所有元素至多出现一次,答案为 n,题目规定 所有元素至多出现两次, 例如 1 1 2,可以排列成 1 2 1,所以,答案为 1 例如 1 1 2 2 3,可以排列成 1 2 3 1 2,所有 答案为 2 思考后得出,应该尽可能的把 b 个出现两次的

Comet OJ - Contest #9 &amp; X Round 3题解

传送门 \(A\) 咕咕 typedef long long ll; int a1,a2,n,d;ll res; int main(){ scanf("%d%d%d",&a1,&a2,&n); d=a2-a1; res=1ll*(a1+a1+1ll*(n-1)*d)*n>>1; printf("%lld\n",res); return 0; } \(B\) 不难发现答案要么是\(1\)要么是\(2\) 当且仅当\(k+1\)是个质

Comet OJ - Contest #13 补题题解

A.险恶的迷宫 题意:在二维平面坐标内,给出一个圆心坐标 (a,b),以及圆的半径 r , 再给出 n 个点的坐标 (x_i,y_i),  求有多少点在圆内. 数据范围:0  <  n  <= 1e5,      0< r , x , y  <=1e9 思路:对于判断距离根据勾股定理: sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)) <= r ,即在圆的范围内.由于此题数据较大,sqrt可能导致精度损失,所以直接开long long 进行平方比较

Comet OJ - Contest #15

https://cometoj.com/contest/79/problem/D?problem_id=4219 题目描述 ※ 简单版与困难版的唯一区别是粗体字部份和 $v$ 的数据范围. 在双 11 时,心慧精品店有个特别的折价活动如下: 首先,我们定义一个正整数为"好的"当且仅当此数仅由数字 1 构成,举例来说 1, 11, 111, 11111 都是「好的」,但 10.123.321 都是「不好的」. 接着,若一个商品原价为 x,若顾客能把 x 表示为 k 个「好的」数字,那么此

[Comet OJ - Contest #4 D][39D 1584]求和_&quot;数位dp&quot;

求和 题目大意: 数据范围: 题解: 脑筋急转弯可还行..... 我们发现只需要最后枚举个位/xk/xk 因为前面的贡献都是确定的了. 故此我们最后暴力统计一下就好咯. 不知道为啥我组合数一直过不去,暴力求过了呜呜. 代码: #include <bits/stdc++.h> using namespace std; typedef long long ll; char *p1, *p2, buf[100000]; #define nc() (p1 == p2 && (p2 =