牛客练习赛29 题解

牛客练习赛29

A. 可持久化动态图上树状数组维护01背包

题解

这题跟标题没有任何关系…

贪心的使得负数删除的时候下标尽可能大,然后正数的时候下标尽可能小.

观察到每个数下标最大的时候就是它的初始下标,下标的最小值是1.

然后贪心一下就好了.

代码

#include <iostream>
using namespace std;
long long a[1000007];
int main(){ios::sync_with_stdio(false);int n;cin >> n;long long sum = 0;for(int i = 1;i <= n;++i){cin >> a[i];if(a[i] >= 0) sum += a[i];else sum += a[i] * i;}cout << sum << endl;
}

B. 列队

题解

有点迷,WA了还没改出来…QAQ

C.枇杷

题解

还没看题

D.禁止动规

题解

根据裴蜀定理,当存在一些x的组合,使得它们的gcd为1的时候,p1x1+p2x2+...+pnxn=1p_1x_1 + p_2x_2 + ... + p_nx_n = 1p1x1+p2x2+...+pnxn=1,方程一定有解.

因此我们就求gcd(x1,x2,...,xn)=1gcd(x_1,x_2,...,x_n) = 1gcd(x1,x2,...,xn)=1的方案数即可

f(x)f(x)f(x)表示gcd(x1,x2,...,xn)=xgcd(x_1,x_2,...,x_n) = xgcd(x1,x2,...,xn)=x的方案数

然后莫比乌斯反演

(⌊mx⌋)n=∑x∣df(d)(\lfloor \frac{m}{x} \rfloor )^n = \sum_{x|d}{f(d)}(xm)n=xdf(d)

得到

f(x)=∑x∣dμ(dx)∗(⌊md⌋)nf(x) = \sum_{x|d}{\mu(\frac{d}{x})*(\lfloor \frac{m}{d} \rfloor )^n}f(x)=xdμ(xd)(dm)n

答案就是
f(1)=∑d=1mμ(d)∗(⌊md⌋)nf(1) = \sum_{d=1}^{m}\mu(d)*(\lfloor \frac{m}{d} \rfloor )^nf(1)=d=1mμ(d)(dm)n

(⌊md⌋)(\lfloor \frac{m}{d} \rfloor )(dm)分块,然后杜教筛求莫比乌斯函数前缀和就可以了.

代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <unordered_map>
#include <map>
#define pr(x) std::cout << #x << ':' << x << std::endl
#define rep(i,a,b) for(int i = a;i <= b;++i)
#define clr(x) memset(x,0,sizeof(x))
#define setinf(x) memset(x,0x3f,sizeof(x))typedef long long ll;
typedef unsigned long long ull;
const int N = 10000000;
ull mu[N+10];int prime[N+10],pcnt,zhi[N+10];
void sieve(){pcnt = 0;mu[1] = zhi[1] = 1;for(int i = 2;i <= N;++i){if(!zhi[i]) mu[i] = -1,prime[pcnt++] = i;for(int j = 0;j < pcnt && prime[j]*i <= N;++j){zhi[i*prime[j]] = 1;if(i % prime[j] == 0){mu[i*prime[j]] = 0;break;}else{mu[i*prime[j]] = -mu[i];}}}for(int i = 1;i <= N;++i) mu[i] += mu[i-1];
}
std::unordered_map<ll,ull> rec,vis;
ull Mu(ll x){if(x <= N) return mu[x];if(vis[x]) return rec[x];ull res = 1,now = x,nxt;while(now >= 2){nxt = x/(x/now+1);res -= (now - nxt) * Mu(x/now);now = nxt;}vis[x] = 1;return rec[x] = res;
}
ll n,m;
ull mod_pow(ull x,ll n) {ull res = 1;while(n) {if(n & 1)res *= x;x *= x;n >>= 1;}return res;
}	
int main() {sieve();unsigned long long ans = 0;std::cin >> n >> m;ll nxt;for(ll x = m;x >= 1;x = nxt) {nxt = m/(m/x+1);ans += mod_pow(m/x,n) * (ull)(Mu(x) - Mu(nxt));}std::cout << ans << std::endl;return 0;
}

E. 位运算?位运算!

题解

补过去了,用这种做法发现被卡常,然后优化了一下常数+快速读入,用了2400ms的样子过掉了.

又是一个新套路,之前不会的新套路.

考虑到要进行区间与区间或还要进行区间求和,那么我们就必须将位拆开来看.

nnn个数拆成202020颗线段树,第iii颗线段树维护这nnn个数上第iii位的信息,线段树区间[l,r][l,r][l,r]表示[l,r][l,r][l,r]区间内的数第iii位上有多少个111.
这样求和就很方便了,按位算贡献即可.

或操作,就相当于把指定线段树的指定区间覆盖成111.与操作就相当于把指定线段树的指定区间覆盖成000.这里在线段树上打lazylazylazy标记即可.

现在问题在于,如何进行循环移位.

我们发现循环移位就相当于线段树之间轮换儿子.

我们可以递归的找到这202020个线段树在该区间下所包含的(完整线段最多lognlognlogn段),然后将它们进行轮换.

代码

#include <iostream>
#include <algorithm>
#include <vector>
#include <cstdio>
#include <cstring>
#include <assert.h>
#define pr(x) std::cout << #x << ':' << x << std::endl
#define rep(i,a,b) for(int i = a;i <= b;++i)
const int N = 200007;
int a[N],root[20],tot;
struct node{int sum,lazy,lch,rch;node(int sum = 0,int lazy = 0,int lch = 0,int rch = 0):sum(sum),lazy(lazy),lch(lch),rch(rch){}
}ns[N*80];
void tag(int o,int len,int lazy) {if(!o) return ;if(lazy == 1)ns[o].sum = len;elsens[o].sum = 0;ns[o].lazy = lazy;
}
void pushdown(int o,int l,int r) {if(ns[o].lazy) {int mid = (l + r) >> 1;tag(ns[o].lch,mid-l+1,ns[o].lazy);tag(ns[o].rch,r-mid,ns[o].lazy);ns[o].lazy = 0;}
}
void set(int o,int l,int r,int cl,int cr,int lazy){if(r < cl || cr < l)return ;if(cl <= l && r <= cr){tag(o,r-l+1,lazy);return ;}int mid = (l + r) >> 1;pushdown(o,l,r);set(ns[o].lch,l,mid,cl,cr,lazy);set(ns[o].rch,mid+1,r,cl,cr,lazy);ns[o].sum = ns[ns[o].lch].sum + ns[ns[o].rch].sum;
}int query(int o,int l,int r,int ql,int qr) {if(r < ql || qr < l)return 0;if(ql <= l && r <= qr)return ns[o].sum;int mid = (l + r) >> 1;pushdown(o,l,r);int lch = query(ns[o].lch,l,mid,ql,qr);int rch = query(ns[o].rch,mid+1,r,ql,qr);return lch + rch;
}void build(int &o,int l,int r,int p) {if(!o)o = ++ tot;if(l == r) {ns[o] = node((a[l]>>p)&1,0,0,0);return ;}int mid = (l + r) >> 1;build(ns[o].lch,l,mid,p);build(ns[o].rch,mid+1,r,p);ns[o].sum = ns[ns[o].lch].sum + ns[ns[o].rch].sum;
}void shift(int *os[],int l,int r,int cl,int cr,int x) {if(r < cl || cr < l)return ;if(cl <= l && r <= cr) {int tmp[20];rep(i,0,19)    tmp[i] = *os[i];rep(i,0,19)*os[i] = tmp[(i+x+20)%20];return ;   }int mid = (l + r) >> 1;rep(i,0,19)pushdown(*os[i],l,r);int *lft[20],*rgt[20];rep(i,0,19)lft[i] = (&(ns[*os[i]].lch)),rgt[i] = (&(ns[*os[i]].rch));shift(lft,l,mid,cl,cr,x);shift(rgt,mid+1,r,cl,cr,x);rep(i,0,19)ns[*os[i]].sum = ns[ns[*os[i]].lch].sum + ns[ns[*os[i]].rch].sum;
}
int n,q;
inline int read() {char ch = getchar(); int x = 0, f = 1;while(ch < '0' || ch > '9') {if(ch == '-') f = -1;ch = getchar();} while('0' <= ch && ch <= '9') {x = x * 10 + ch - '0';ch = getchar();} return x * f;
}
int main () {n = read();q = read();rep(i,1,n)a[i] = read();rep(i,0,19)build(root[i],1,n,i);rep(i,1,q) {int op,l,r,v;op = read(),l = read(),r = read(),v = read();if(op == 1 || op == 2) {int *os[20];rep(i,0,19)os[i] = &root[i];  shift(os,1,n,l,r,v*(op == 1?1:-1));}  else if(op == 3) {rep(i,0,19)if((v >> i) & 1)set(root[i],1,n,l,r,1);}else if(op == 4) {rep(i,0,19)if(((v >> i) & 1) == 0)set(root[i],1,n,l,r,-1);}else {long long ans = 0;rep(i,0,19)ans += query(root[i],1,n,l,r) * (1LL<<i);printf("%lld\n",ans);}}
}

F. 算式子

题解

对于每一个x∈[1,m]x \in [1,m]x[1,m],都要计算下面的式子.
∑i=1n(⌊aix⌋+⌊xai⌋)\sum_{i=1}^{n} (\lfloor \frac{a_i}{x} \rfloor + \lfloor \frac{x}{a_i} \rfloor)i=1n(xai+aix)

这个式子可以拆成两部分来求,即
⌊aix⌋\lfloor \frac{a_i}{x} \rfloorxai⌊xai⌋\lfloor \frac{x}{a_i} \rflooraix.

第一部分容易求

xxx固定时计算介于[x,2x),[2x,3x)....[x,2x),[2x,3x)....[x,2x),[2x,3x)....aia_iai有多少个,讲贡献计入ans1[x]ans_1[x]ans1[x].

第二部分就不那么直观了

我们设ans2[x]=∑i=1n⌊xai⌋ans_2[x] = \sum_{i=1}^n \lfloor \frac{x}{a_i} \rfloorans2[x]=i=1naix

对于每一个aia_iai其中x∈[ai,2ai)x \in [a_i,2a_i)x[ai,2ai)ans2ans_2ans2应该得到影响111,所以我应该给ans2[ai,2ai)ans_2[a_i,2a_i)ans2[ai,2ai)数组进行区间+1+1+1.而x∈[ai,2ai)x \in [a_i,2a_i)x[ai,2ai)的应该得到影响222,所以我应该给ans2[2ai,3ai)ans_2[2a_i,3a_i)ans2[2ai,3ai)数组进行区间+2+2+2…依次类推…
具体实现的话,我们线段ans2ans_2ans2求一个差分数组deltadeltadelta,那么我对于ans2ans_2ans2[l,r][l,r][l,r]区间+d+d+d,就相当于对差分数组delta[l]+=d,delta[r+1]−=ddelta[l]+=d,delta[r+1]-=ddelta[l]+=d,delta[r+1]=d,最后,对差分数组求前缀和就可以恢复成ans2ans_2ans2数组.

总的时间复杂度O(nlogn)O(nlogn)O(nlogn)

代码

#include <iostream>const int N = 2000007;
int n,m;
long long a[N];
long long num[N],cnt[N],cnt2[N];
long long ans[N];
int main() {std::ios::sync_with_stdio(false);std::cin >> n >> m;for(int i = 0;i < n;++i) {std::cin >> a[i];cnt[a[i]] ++ ;num[a[i]] ++ ;}for(int i = 0;i <= m;++i) cnt[i] += cnt[i-1];long long res = 0;for(int x = 1;x <= m;++x) {int y = 2*x;for(;y <= m;y += x) {ans[x] += (cnt[y-1] - cnt[y-x-1])*((y-1)/x);}ans[x] += (cnt[m] - cnt[y-x-1])*(cnt[m]/x);}for(int i = 1;i <= m;++i) {cnt2[i] += num[i];for(int j = 2*i;j <= m;j += i) {cnt2[j] += num[i];}}for(int x = 1;x <= m;++x) {cnt2[x] += cnt2[x-1];ans[x] += cnt2[x];res ^= ans[x];}std::cout << res << std::endl;return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/321041.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Floyed】小萨的烦恼(ssl 1624)

小萨的烦恼 ssl 1624 题目大意&#xff1a; 一个无向图&#xff0c;可以使其中一条道路的值除以2&#xff0c;求两个点之间的最短路 原题&#xff1a; Description 圣诞节又要到了&#xff01;小萨希望和自己心仪的MM一起出去度过一个浪漫的的圣诞节。他进行了详尽的准备…

好代码是管出来的——使用GitHub

前面的文章介绍了Git的基本概念和用法&#xff0c;本文则是基于GitHub的一个实践介绍&#xff0c;主要内容有&#xff1a;GitHub简介个人与组织仓库的创建与维护Fork与pull request小结GitHub简介GitHub是一个Git的远程代码托管平台&#xff0c;它除了提供代码托管外&#xff0…

Wannafly挑战赛24

Wannafly挑战赛24 题目连接 https://www.nowcoder.com/acm/contest/186#question A.石子游戏 题解 注意到当石子个数为偶数的时候,每回合都会减少一堆偶数石子,因此,先手必胜. 我们可以不考虑奇数堆石子,因为必胜方始终可以动偶数堆. 当必败方将奇数堆分成一堆偶数和一堆…

【模拟】正方形

正方形 题目大意&#xff1a; 有三个人&#xff0c;一人一笔的画正方形&#xff0c;每个正方形是上一个正方形每条边上的中点连接而成的&#xff0c;求每个人画了多长 原题&#xff1a; 题目描述 又到暑假啦&#xff0c;Conan, Ayumi, Mitsuhiko, Genta一起到Hakase家愉快…

P3975-[TJOI2015]弦论【SAM】

正题 题目链接:https://www.luogu.com.cn/problem/P3975 题目大意 给一个字符串sss和t,kt,kt,k。求字符串sss第kkk大的子串。 当T0T0T0时&#xff0c;相同的子串算一个当T1T1T1时&#xff0c;不同位置的相同子串算不同的串 解题思路 当T0T0T0时很简单&#xff0c;对于每个位…

【DP】跳格子

跳格子 题目大意&#xff1a; 有一堆格子&#xff0c;可以往前跳不超过当前格子上的数的步数&#xff0c;从1跳到最后一格最少要跳多少 原题&#xff1a; 题目描述 大家都说要劳逸结合&#xff0c;Ayumi, Mitsuhiko, Genta画完方格就出去运动啦&#xff01; 他们来到了一片…

.NET Core微服务之基于IdentityServer建立授权与验证服务

一、IdentityServer的预备知识要学习IdentityServer&#xff0c;事先得了解一下基于Token的验证体系&#xff0c;这是一个庞大的主题&#xff0c;涉及到Token&#xff0c;OAuth&OpenID&#xff0c;JWT&#xff0c;协议规范等等等等&#xff0c;园子里已经有很多介绍的文章了…

模拟退火求解TSP问题

模拟退火求解TSP问题 模拟退火算法步骤 1.寻找下一个解 2.计算下一个解的能量 3.决定是否接受这个解 4.降温 算法模板 double randfloat() {return rand()/(RAND_MAX0.0); }double T0 1000000,Tk 1,T T0,d 0.9999; int x initx();//当前解(初始解) int ansE,nowE;//全…

P2444-[POI2000]病毒【AC自动机】

正题 题目链接:https://www.luogu.com.cn/problem/P2444 题目大意 nnn个字符串&#xff0c;求有没有一个无限的字符串不包含任何一个给出的字符串。 解题思路 考虑ACACAC自动机的匹配方式&#xff0c;不过每次我们可以每次在构出的TrieTrieTrie树上随意走&#xff08;就是求完…

【模拟】2048

2048 题目大意&#xff1a; 模拟2048游戏 原题&#xff1a; 题目描述 此时&#xff0c;Conan却在一旁玩着2048。 这是一个4*4的矩阵&#xff0c;初始全为0。每次一个没有数字的格子中会随机出现一个2或4&#xff0c;每次可以选择上下左右其中一个方向去滑动&#xff0c;每…

在Docker中部署Asp.net core2.1以及修改发布

本篇文章主要是如何在Docker容器中运行ASP.NET Core应用程序&#xff0c;以及修改系统之后&#xff0c;发布更新。本文章采用自定义的Docker文件系统要求&#xff1a;1.服务器或本地已经安装docker一、创建一个Asp.Net Core 2.1 Web应用&#xff08;若可以熟练创建项目&#xf…

HDU5322 - cdq分治FFT加速dp

5322 Hope [CDQ分治FFT加速计算dp] 题意 每一个每一个排列,排列中每个数向它后面第一个比它大的数连一条边. 每个排列对于答案的贡献是这个排列所生成的图中的每一个联通量中点的个数的平方之积. 例如:排列 1,2,3,6,4,51,2,3,6,4,51,2,3,6,4,5 其中 1,2,3,61,2,3,61,2,3,6形…

AT2300-[ARC068C]Snuke Line【整除分块】

正题 题目链接: https://www.luogu.com.cn/problem/AT2300 https://atcoder.jp/contests/arc068/tasks/arc068_c 题目大意 有mmm个车站&#xff0c;nnn种礼品&#xff0c;第iii种可以在[li,ri][l_i,r_i][li​,ri​]的车站买到&#xff0c;第ddd辆车会近过编号为ddd的倍数的车…

【二分】游戏

游戏 题目大意&#xff1a; 有三个套餐&#xff0c;1&#xff1a;一个a、一个b和一个c,2&#xff1a;一个a和两个b&#xff0c;3&#xff1a;两个a和一个b&#xff0c;现在有一定的a、b和c&#xff0c;要使任意两个形同的套餐不相邻&#xff0c;问最多可以有多少个套餐&#…

要用Identity Server 4 -- OAuth 2.0 超级简介

OAuth 2.0 简介OAuth有一些定义:OAuth 2.0是一个委托协议, 它可以让那些控制资源的人允许某个应用以代表他们来访问他们控制的资源, 注意是代表这些人, 而不是假冒或模仿这些人. 这个应用从资源的所有者那里获得到授权(Authorization)和access token, 随后就可以使用这个access…

清明梦超能力者黄YY[树链剖分+扫描线,线段树合并]

清明梦超能力者黄YY 题目连接 https://www.nowcoder.com/acm/contest/206/I 暂时有两种做法. 算法一 涉及:树链剖分,扫描线 在一个线段的情况下,我们可以把一个染色区间拆成左端点处增加事件,右端点处删除事件. 维护一颗权值线段树. 这样,端点从小到大扫描时,遇到增加事件…

初一模拟赛总结(3.23)

成绩&#xff1a; rankrankranknamenamenamescorescorescoreT1T1T1T2T2T2T3T3T3T4T4T4111lyflyflyf300300300100100100100100100100100100000222wjjwjjwjj290290290100100100100100100909090000333hkyhkyhky270270270100100100100100100707070000444fyfyfy24024024010010010010…

CF1110E-Magic Stones【结论题,差分】

正题 题目链接:https://www.luogu.com.cn/problem/CF1110E 题目大意 给出一个序列cic_ici​和一个序列tit_iti​。每次操作可以将cici−1ci1−ci(1<i<n)c_ic_{i-1}c_{i1}-c_i(1<i<n)ci​ci−1​ci1​−ci​(1<i<n) 解题思路 首先要求c1t1,cntnc_1t_1,c_nt…

好代码是管出来的——C#的代码规范

代码是软件开发过程的产物&#xff0c;代码的作用是通过编译器编译后运行&#xff0c;达到预期的效果(功能、稳定性、安全性等等)&#xff0c;而另外一个重要作用是给人阅读。对于机器来说只要代码正确就能够正确的运行程序&#xff0c;但是人不同&#xff0c;如果代码编写混乱…

【图论】【高精】产生数(ssl 1021/ luogu 1037)

产生数 ssl 1021 luogu 1037 题目大意&#xff1a; 有一个数&#xff0c;可以使某些数字变成相对应的数字&#xff0c;问有多少种变法 原题&#xff1a; Description 给出一个整数 n&#xff08;n<10^30) 和 k 个变换规则&#xff08;k<15&#xff09;。   规则…