文章目录
- 前言
- 题目解析
- 最小划分(divide)
- 进制路径(base)
- 欧拉欧拉(eular)
- 代码
- T1
- T2
- T3
- 总结
前言
day9
170pts
期望:100+100+20=220
实际:70+100+0=170
rnk7
挂的分有点多qwq
分数要是得满就能拿牌子乐…
T1加了个画蛇添足的东西,导致白给了30
T3暴搜T掉了,需要引以为戒,其实加个小优化就行了。
题目解析
最小划分(divide)
应该算是科技题吧。
WQS二分模板题,由于这个算法不是太冷门,A的人也非常多。
选取个数还是要按照 >= 二分…
而且,不要在个数不等于 mmm 的时候强制转移!本来啥也不干就是对的。
结合WQS的实质也是合理的,只是恰好多个点落在了这条直线上,不影响我用截距求出函数值,如果我最后一步强制按照取 mmm 个转移,就会破坏最优性,得到错误的截距。
理解至上。
进制路径(base)
爆肝码农题。
但做法确实不太难想,用主席树和线段树二分模拟一下高精加与比较即可。
但是加法需要一个区间推平操作,带懒标记的主席树是真的恶心…
时空复杂度应该都是 O((n+m)lognlogV)O((n+m)\log n\log V)O((n+m)lognlogV),从加法操作的次数来看空间看起来似乎只有 O(mlogV)O(m\log V)O(mlogV),但是由于其他的查询操作需要 pushdown
,开更多的点,所以其实空间复杂度也是两个 log 的。
题解的实现是直接把推平的区间链接到一棵空的线段树的对应结点上,可以把空间复杂度优化到单log。
欧拉欧拉(eular)
真不是我磕巴
KH这题做法真的踩标算了,请收下我的膝盖!
之前莫反做的挺明白的,这题没做出来有些可惜。
主要就是脑子有点抽筋了,对于多个数的 lcm
,忘记它还可以是每个质因子幂次的最大值。
由于欧拉函数是积性函数,可以单独考虑枚举每一个质数 ppp 的贡献。
我们有:φ(pk)=pk−1(p−1)\varphi(p^k)=p^{k-1}(p-1)φ(pk)=pk−1(p−1)
因此 ppp 这个质数的总贡献必然是 (p−1)apb(p-1)^ap^b(p−1)apb 的样子。
首先,ppp 必然要出现至少一次,这样的序列有 nk−⌊np⌋kn^k-\lfloor\frac{n}{p}\rfloor^knk−⌊pn⌋k 个。
因此 p−1p-1p−1 的贡献幂次 aaa 就是 nk−⌊np⌋kn^k-\lfloor\frac{n}{p}\rfloor^knk−⌊pn⌋k。
然后考虑如何求 bbb。
一开始所有序列的贡献都是 0。
设一个序列中 ppp 的最高次数为 mxmxmx,那么 mx≥wmx\ge wmx≥w 的序列应该有 nk−⌊npw⌋kn^k-\lfloor\frac{n}{p^w}\rfloor^knk−⌊pwn⌋k 个。
我们从 2 开始枚举 www,然后每次把对应的序列的贡献视为 1。
那么一个 mx=xmx=xmx=x 的序列,其就会贡献 x−1x-1x−1 次贡献,正好符合题意。(这也算是一种统计的常见技巧了)
大道至简,优美。
总复杂度大概是小于单log的。
看完这个做法,题解的做法就…
但是这个 min-max 容斥还挺秀的。
后面就是比较常规的大反演了。
代码
T1
#include<bits/stdc++.h>
using namespace std;
#define ll __int128
#define ull unsigned long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define ok debug("OK\n")
inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f;
}
void write(ll x){if(x>9) write(x/10);putchar('0'+x%10);
}
const int N=2e5+100;int n,m;#define X(o) (2*s[o])
#define Y(o) (dp[o]+s[o]*s[o]-2*p*s[o])ll s[N],dp[N],p;
int num[N],q[N],st,ed;void solve(ll w,int op=0){q[st=ed=1]=0;for(int i=1;i<=n;i++){while(st<ed&&s[i]*(X(q[st+1])-X(q[st]))>=(Y(q[st+1])-Y(q[st]))) ++st;int j=q[st];dp[i]=dp[j]+(s[i]-s[j]+p)*(s[i]-s[j]+p)+w;num[i]=num[j]+1;while(st<ed&&(Y(i)-Y(q[ed]))*(X(q[ed])-X(q[ed-1]))<=(Y(q[ed])-Y(q[ed-1]))*(X(i)-X(q[ed]))) --ed;q[++ed]=i;//printf("i=%d j=%d dp=%lld (%lld %lld)\n",i,j,dp[i],X(i),Y(i));//for(int j=st;j<=ed;j++) printf("%d:(%lld %lld) ",q[j],X(q[j]),Y(q[j]));//puts("\n");}//printf("w=%lld num=%d dp=%lld\n",w,num[n],dp[n]);return;
}signed main(){freopen("divide.in","r",stdin);freopen("divide.out","w",stdout);n=read();m=read();p=read();for(int i=1;i<=n;i++) s[i]=read()+s[i-1];//solve(308);return 0;ll st=-1e16,ed=1e16;while(st<ed){ll mid=(st+ed+1)>>1;solve(mid);if(num[n]>=m) st=mid;else ed=mid-1;}solve(st,1);write(dp[n]-m*st);return 0;
}
/*
5
aabba
*/
T2
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define ok debug("OK\n")
inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f;
}
void write(ll x){if(x>9) write(x/10);putchar('0'+x%10);
}
const int N=2e5+100;
const int mod=1e9+7;int n,m,s,t,o;struct node{int to,nxt,w;
}p[N<<1];
int fi[N],cnt;
inline void addline(int x,int y,int w){p[++cnt]=(node){y,fi[x],w};fi[x]=cnt;
}
int pre[N],a[N],num;
void print(int x){if(pre[x]) print(pre[x]);a[++num]=x;
}
ll dis[N];
ull mi[N];
int u[N],v[N],ww[N];
int vis[N];
#define pr pair<ll,int>
#define mkp make_pair
priority_queue<pr,vector<pr>,greater<pr> >q;void bf(){mi[0]=1;for(int i=1;i<=o;i++) mi[i]=mi[i-1]<<1;for(int i=1;i<=m;i++){addline(u[i],v[i],mi[ww[i]]);addline(v[i],u[i],mi[ww[i]]);}memset(dis,0x3f,sizeof(dis));dis[s]=0;q.push(mkp(0,s));while(!q.empty()){int now=q.top().second;q.pop();if(vis[now]) continue;vis[now]=1;for(int i=fi[now];~i;i=p[i].nxt){int to=p[i].to;if(dis[to]>dis[now]+p[i].w){dis[to]=dis[now]+p[i].w;q.push(mkp(dis[to],to));pre[to]=now;}}}if(pre[t]||s==t){printf("%lld\n",dis[t]%mod);print(t);printf("%d\n",num);for(int i=1;i<=num;i++) printf("%d ",a[i]);puts("");}else puts("-1");return;
}ull hh[N][2];
#define mid ((l+r)>>1)
const int key=3;
struct tree{int ls,rs,sum,laz;ull h;
}tr[N*200];
int tot;
inline void pushup(int k,int l,int r){tr[k].sum=tr[tr[k].ls].sum+tr[tr[k].rs].sum;tr[k].h=tr[tr[k].rs].h*mi[mid-l+1]+tr[tr[k].ls].h;return;
}
inline int copy(int x){tr[++tot]=tr[x];return tot;
}
inline void add(int &k,int l,int r,int w){k=copy(k);tr[k].sum=(r-l+1)*w;tr[k].laz=w;tr[k].h=hh[r-l+1][w];return;
}
inline void pushdown(int k,int l,int r){if(l==r) return;int o=tr[k].laz;tr[k].laz=-1;if(o==-1) return;add(tr[k].ls,l,mid,o);add(tr[k].rs,mid+1,r,o);return;
}
void build(int &k,int l,int r,int w){k=copy(0);if(l==r){tr[k].sum=tr[k].h=w;hh[r-l+1][w]=tr[k].h;return;}build(tr[k].ls,l,mid,w);build(tr[k].rs,mid+1,r,w);pushup(k,l,r);hh[r-l+1][w]=tr[k].h;return;
}
int findsuf(int k,int l,int r,int pl){if(tr[k].sum==r-l+1) return r-pl+1;if(l==r) return 0;pushdown(k,l,r);if(pl>mid) return findsuf(tr[k].rs,mid+1,r,pl);else{int res=findsuf(tr[k].ls,l,mid,pl);if(res==mid-pl+1) return res+findsuf(tr[k].rs,mid+1,r,mid+1);else return res;}
}
void upd(int &k,int l,int r,int x,int y,int w){//printf("upd: (%d %d) (%d %d) w=%d\n",l,r,x,y,w);if(x>y) return;if(x<=l&&r<=y){add(k,l,r,w);return;}pushdown(k,l,r);k=copy(k);if(x<=mid) upd(tr[k].ls,l,mid,x,y,w);if(y>mid) upd(tr[k].rs,mid+1,r,x,y,w);pushup(k,l,r);return;
}
bool cmp(int x,int y,int l,int r){// x<y ? 1:0if(tr[x].h==tr[y].h) return 0;if(l==r) return tr[x].sum<tr[y].sum;pushdown(x,l,r);pushdown(y,l,r);if(tr[tr[x].rs].h!=tr[tr[y].rs].h) return cmp(tr[x].rs,tr[y].rs,mid+1,r);else return cmp(tr[x].ls,tr[y].ls,l,mid);
}
struct bign{int rt;void plus(int w){int len=findsuf(rt,1,o,w);upd(rt,1,o,w,w+len-1,0);upd(rt,1,o,w+len,w+len,1);return;}bool operator < (const bign &oth)const{return cmp(rt,oth.rt,1,o);}
}d[N];
struct Dis{bign dis;int id;bool operator < (const Dis &oth)const{if(tr[dis.rt].h==tr[oth.dis.rt].h) return id>oth.id;else return oth.dis<dis;}
};
priority_queue<Dis>que;
ll ans,mi2[N];
void calc(int k,int l,int r){if(l==r){ans=(ans+tr[k].sum*mi2[l-1])%mod;return;}pushdown(k,l,r);calc(tr[k].ls,l,mid);calc(tr[k].rs,mid+1,r);return;
}
void solve(){o+=20;mi2[0]=1;for(int i=1;i<=o;i++) mi2[i]=(mi2[i-1]<<1)%mod;mi[0]=1;for(int i=1;i<=o;i++) mi[i]=mi[i-1]*key;for(int i=1;i<=m;i++){++ww[i];addline(u[i],v[i],ww[i]);addline(v[i],u[i],ww[i]);}build(d[0].rt,1,o,1);//rt[0]=inffor(int i=1;i<=n;i++) d[i].rt=d[0].rt;build(d[s].rt,1,o,0);que.push((Dis){d[s],s});while(!que.empty()){int now=que.top().id;que.pop();if(vis[now]) continue;vis[now]=1;for(int i=fi[now];~i;i=p[i].nxt){int to=p[i].to,w=p[i].w;bign res=d[now];res.plus(w);if(res<d[to]){d[to]=res;que.push((Dis){d[to],to});pre[to]=now;}}}if(!pre[t]&&s!=t) puts("-1");else{calc(d[t].rt,1,o);//debug("dis=%lld\n",ans);printf("%lld\n",ans);print(t);printf("%d\n",num);for(int i=1;i<=num;i++) printf("%d ",a[i]);}return;
}signed main(){freopen("base.in","r",stdin);freopen("base.out","w",stdout);//printf("%d\n",sizeof(tr)/1024/1024);memset(fi,-1,sizeof(fi));cnt=-1;tr[0].laz=-1;n=read();m=read();s=read();t=read();for(int i=1;i<=m;i++){u[i]=read();v[i]=read();ww[i]=read();o=max(o,ww[i]);}if(o<=20) bf();else solve();//solve();return 0;
}
/*
5
aabba
*/
T3
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define ok debug("OK\n")
inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f;
}
void write(ll x){if(x>9) write(x/10);putchar('0'+x%10);
}
const int N=2e6+100;
const int mod=1e9+7;inline ll ksm(ll x,ll k,ll mod){ll res(1);while(k){if(k&1) res=res*x%mod;x=x*x%mod;k>>=1;}return res;
}int n,k;
int prime[N],vis[N],tot;
void init(int n){++n;for(int i=2;i<=n;i++){if(!vis[i]){prime[++tot]=i;}for(int j=1;j<=tot&&prime[j]<=n/i;j++){int now=prime[j];vis[i*now]=1;if(i%now==0) break;}}return;
}signed main(){freopen("euler.in","r",stdin);freopen("euler.out","w",stdout);n=read();k=read();init(max(k,n));ll ans(1);for(int o=1;o<=tot;o++){ll p=prime[o];ans=ans*ksm(p-1,ksm(n,k,mod-1)+(mod-1)-ksm(n-n/p,k,mod-1),mod)%mod;ll now=p*p;while(now<=n){ans=ans*ksm(p,ksm(n,k,mod-1)+mod-1-ksm(n-n/now,k,mod-1),mod)%mod;now*=p;}}printf("%lld\n",ans);return 0;
}
/*
5
aabba
*/
总结
今天感觉整体题目要偏易一些。
但是挂的分有点多了,而且T3实属可惜,其实对每个质数单独考虑的做法我也不是没有想过…
(现在对题目的“感觉”还是变好了一些,做不出的题见到solution也基本上都有“其实想过”的过程。)
但是还是要敢推敢想吧。
既要敢于创造性的思考,也要在遇阻时尝试多线思维。
另外,今天节奏还是不错的。
明天加油吧!awa