long long 、祖宗、懂?
离散化后解决后输出方案时记得还原回离散化前的值!
\(f(x)=10x+1\bmod p\) 一直递归可能不是环,而是 \(\rho\) 形的,所以环长不等于总长度。
然后还要判余数,和 \(n\) 根本走不到 \(\rho\) 的环的情况,反正难调 + 对拍长 + 写得丑。
不要把小于号给重定义成小于等于啊啊啊,会有 TLE 到 WA 不等的蜜汁错误。
不要把前缀和数组直接单点求值来取单点的值 qwq。
做多项式题输入数组和输出数组尽量不要相同,说不定打架了,况且不好调试。
新科技:Lambda 匿名函数
将一个数 \(n\) 用 \(O(\sqrt{n})\) 质因数分解算法后记得判 \(n'\ne 1\) 的情况。
一道分块题。
块长设为 \(B=400\),数列长度为 \(10^5\),开了 \(N=10^5+3\)。
然后存每一个块的 delta,数组开了 \(\frac{N}{B}\),但是从 \(1\) 开始下标,少开一位!一——位——啊——!(调了 4h 写了对拍)。
下次再这种 sb 错误我就是歌姬。
kasumi 前建初始矩阵时要 +=
不能 =
(懂我意思吧)。
也就是说,AC 自动机上可能有重边,需要累加。
AC 自动机判断子串要从 x->fail 传向 x。
这里 splay 指针版不需要记录每个元素的指针,要记录 root,因为有区间 reverse,会改变,查找时直接二分(BST)就行。
而 LCT 中却正好反过来,因为我们要记录点的标号,而且 reverse 操作不会影响标号。不用记录 root。
由欧拉公式
\[e^{ix}=\cos x+i\sin x \]得到
\[\begin{matrix} &(\cos \alpha &+i&\sin \alpha ) \\ \times &(\cos \beta &+i&\sin \beta ) \\ =&(\cos(\alpha+\beta)&+i&\sin(\alpha+\beta)) \end{matrix} \]就是高一的和差角公式了。
这样我们线段树维护这个复数、复数乘 lazy tag 即可。
平衡树 pushup 时 rt.sz 不是 +1 而是 +rt.cnt。
vector
存有向图删重边:
sort(e[i].begin(),e[i].end()); e[i].erase(unique(e[i].begin(),e[i].end()),e[i].end());
网络流边的 tot 初始为 \(1\)!!!!!!!!!!!!!!!!!!!!!!
太久没写网络流了,调了 114514 年。
网络流拆点,点的数组没开两倍。
显然每条原边 \(u\leftrightarrow v(u<v)\) 在费用流中建 \(u'\to v\),费用为 \(0\)。
但是容量为多少呢?我当时以为每个点最多只能走一次,所以写了容量为 \(1\),就快乐 WA 了。
原因:\(1\leftrightarrow n\),可以 \(1\to n\to 1\) 这样游,这条边经过 \(2\) 次。
所以我们得建容量为 \(1\) 的边两遍 qwq。
一道 Ynoi,肥肠卡常,搞了两天(做法放在简思短解)。
真正的跳坑:
无序插入的数组不排序直接二分 lower_bound(甚至调了半天)/qd。
被排除的忘记判断直接做了,导致错误。
介绍卡常:
将 vector 改用前向星。
将两次前向星改为一次,时空均减。
改用 scanf。
函数加 inline,将不必要的函数直接拆开。
去掉冗余的树状数组查询,以及 que(x)-que(x-1)(因单点修改区间询问,直接存原序列求单点)。
将前向星改为指针版的(首次尝试这样写),不过好像还变慢了??
将数组大小更接近真实值。
将树状数组 que 中 x-=low(x) 改为 x^=low(x),不过效果不明显。
改 long long,不需要 64 位的用 32 位。
将 求两次 lower_bound 求区间后遍历 改为 一次左端点二分,遍历时判断是否越右端点(效果显著)。
改用 buf 快读(首次尝试)。
此时已经 517ms(时限 500ms),将编译从 c++14 O2 改成 c++98 O2 就蜜汁过了(不可思议)。
最后附上代码(非指针版前向星)
//Said no more counting dollars. We'll be counting stars. #include<bits/stdc++.h> using namespace std; #define For(i,j,k) for(int i=j;i<=k;i++) #define Rof(i,j,k) for(int i=j;i>=k;i--) #define N 100002 #define V 500002 #define C 20000002 #define ll long long #define low (x&(-x)) char buf[1<<21],*p1,*p2; #define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) #define rg register inline int read() { rg int x=0,f=1; rg char c=gc(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc();} while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48);c=gc();} return x*f; } inline long long lread() { rg long long x=0,f=1; rg char c=gc(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc();} while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48);c=gc();} return x*f; } int n,m,g[N],lim=0; ll c[N]; inline void add(int x,int y){ while(x<=n){ c[x]+=y; x+=low; } } inline ll que(int x){ ll res=0; while(x){ res+=c[x]; x-=low; } return res; } struct node{int nxt,id;}e[N]; int head[V],tot=0,d[C],cnt[V],L[V],R[V],f[C]; inline int gf(int x){return (x^f[x])?f[x]=gf(f[x]):x;} #define lb lower_bound inline void work(int l,int r,int w){ int i=gf(lb(d+L[w],d+R[w],l)-d),val; while(d[i]<=r && i<R[w]){ val=g[d[i]]; if(val%w){ f[i]=gf(i+1); }else{ add(d[i],val/w-val); g[d[i]]=val/w; } i=gf(i+1); } } int main(){ n=read();m=read(); int x; For(i,1,n){ g[i]=x=read(); if(!x) continue; if(lim<x) lim=x; add(i,x); cnt[x]++; e[++tot]=(node){head[x],i};head[x]=tot; } For(i,1,lim) for(int j=i;j<=lim;j+=i) L[i+1]+=cnt[j]; For(i,2,lim) L[i]+=L[i-1]; For(i,1,lim) R[i]=L[i]; For(i,1,lim) for(int j=i;j<=lim;j+=i) for(int k=head[j];k;k=e[k].nxt) d[R[i]++]=e[k].id; For(i,1,lim) sort(d+L[i],d+R[i]); For(i,0,R[lim]) f[i]=i; int opt; ll lst=0,l,r,w; while(m--){ opt=read();l=lread()^lst;r=lread()^lst; if(opt==1){ w=lread()^lst; if(w==1) continue; work(l,r,w); }else{ lst=que(r)-que(l-1); printf("%lld\n",lst); } } return 0;}
给定两个数 \(a,b\),每次可以将一个 \(-1\),另一个 \(-2\),求使得两个均非正的最小次数。
我们不妨设 \(a\le b\)。
若 \(2a\le b\),则我们每次都把 \(-2\) 给 \(b\),这样答案是 \(\lceil\frac{b}{2}\rceil\)。
否则,我们先给 \(b\) 每次 \(-2\),\(a\) 每次 \(-1\),直到使得 \(a=b\)。我们再用两种消减方式 \(\{-1,-2\},\{-2,-1\}\) 交替搞 \(a,b\)。
通过分类讨论剩余 \(\%3\),设 \(c=2a-b\),则得到答案为
\[(b-a)+\lfloor\frac{2}{3}c\rfloor+(c\bmod 3) \]判无解优先于判无穷解!!!
代码
建网络流的时候一定不要吝啬空间,记得精细算点数,边数(开两倍)。
qwq 被坑惨了。
题意转化为:给一个图,让划分成两个点集 \(S,T\),使得 \(S,T\) 分别为独立集,\(n\le 100\)。当然希望两个子集大小尽量相同(靠近 \(n/2\)),然后输出方案。
首先跑二分图。然后对于每一个连通块有两部分各自独立的点集。然后相当于分组背包了,最后体积要尽量接近 \(n/2\)。
坑点 1:分组背包中要二选一,不能不选(这个调了一下午qwq)。
坑点 2:多重背包不能滚动,因为要找方案(调了一晚上qwq)。
总计交了 20 遍。
//Said no more counting dollars. We'll be counting stars. #pragma GCC optimize("Ofast") //#pragma GCC optimize("unroll-loops")//DONT use rashly,I have suffered //#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,tune=native")//DONT use rashly,I have suffered #include<bits/stdc++.h> using namespace std; #define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0) #define fir first #define sec second #define mkp make_pair #define pb emplace_back #define mem(x,y) memset(x,y,sizeof(x)) #define For(i,j,k) for(int i=j;i<=k;i++) #define Rof(i,j,k) for(int i=j;i>=k;i--) #define Fe(x,y) for(int x=head[y];x;x=e[x].nxt) #define ckmx(a,b) a=max(a,b) #define ckmn(a,b) a=min(a,b) #define fin(s) freopen(s,"r",stdin) #define fout(s) freopen(s,"w",stdout) #define file(s) fin(s".in");fout(s".out") #define cerr cerr<<'_' #define debug cerr<<"Passed line #"<<__LINE__<<endl template<typename T>T ov(T x){cerr<<"Value: "<<x<<endl;return x;} #define ll long long const ll mod=1000000007; inline ll pw(ll x,ll y){ll r=1;while(y){if(y&1)r=r*x%mod;x=x*x%mod;y>>=1;}return r;} inline void mad(ll &a,ll b){a=(a+b)%mod;while(a<0)a+=mod;} inline void mmu(ll &a,ll b){a=a*b%mod;while(a<0)a+=mod;} #define inv(a) pw(a,mod-2) #define int long long #define N 110 //405. 将他们分好队 int n,tot=1; int f[N][N]; int cnt[2*N]; bool a[N][N],flag=1,out[2*N]; vector<int> e[N]; int col[N]; void dfs(int x,int y){ col[x]=y; cnt[y]++; For(i,1,n) if(a[x][i] || a[i][x]){ if(col[i]==y){ flag=0; return ; }else if(!col[i]) dfs(i,y^1); } } signed main(){IOS; cin>>n; int x; For(i,1,n) For(j,1,n) a[i][j]=(i!=j); For(i,1,n){ while(1){ cin>>x; if(!x) break; a[i][x]=0; } } For(i,1,n) if(!col[i]){ tot+=2; dfs(i,tot); if(!flag){ cout<<"No solution"<<endl; return 0; } } mem(f,-1); f[0][0]=0; for(int i=2;i<=tot;i+=2){ Rof(j,n,0){ if(j-cnt[i]>=0 && f[i/2-1][j-cnt[i]]>=0) f[i/2][j]=i; else if(j-cnt[i^1]>=0 && f[i/2-1][j-cnt[i^1]]>=0) f[i/2][j]=i^1; } } int ans=0; For(i,1,n) if(f[tot/2][i]>=0 && abs(n-2*i)<abs(n-2*ans)) ans=i; Rof(i,tot/2,1){ out[f[i][ans]]=1; ans-=cnt[f[i][ans]]; } For(i,1,n) if(out[col[i]]) ans++; cout<<ans; For(i,1,n) if(out[col[i]]) cout<<" "<<i; cout<<endl; cout<<n-ans; For(i,1,n) if(!out[col[i]]) cout<<" "<<i; cout<<endl; return 0;}
传递闭包不会写了 qwq。
错误的:
For(k,1,n) For(i,1,k-1) For(j,1,k-1) f[i][j]|=f[i][k]&f[k][j];
正确的:
For(k,1,n) For(i,1,n) For(j,1,n) f[i][j]|=f[i][k]&f[k][j];
网络流建图的时候下标一定要算好,不能重叠 qwq。
矩阵乘法 a.mul(b)
是乘法,不是 *=
。(话说为啥把 a.mul(a);
放在 main
里不 warning?)
map 最好不要用下标访问不存在的节点,最好之前判断一下 mp.find(...)==mp.end()
。
这道题就被卡时间了,别的题可能卡空间,因为:
访问不存在的节点会让 map 新建这个节点,时间慢。
多次新建后 \(n\)(在 map 中的个数)增大,\(\log n\) 随之增大。
多次新建后空间可能会爆。
算 \(\sum\limits_i(x+ki)^2\) 类似的东西,我用类似平方和前缀和相减的方法算,但是 \(k\) 可以是 \(0\),然后除数就是 \(0\) 崩掉 RE 一直调不出来。