2022NOIP A层联测27
下发文件(密码为原 accoders 比赛密码)
天平
搜索.
一个简单的性质:只要选出的砝码的 gcd 和所有砝码的 gcd 相等,这个组合就是合法的.
就拿样例举例:
3 15 25 9
可以发现怎么组合都是只有 9 和 25 组合才能消掉 15.
直接爆搜,然后就有了 98 分的好成绩.
拿一个后缀和优化,如果选到当前这个数,再选后面的所有数都比要求的 gcd 大,直接返回.
点击查看代码
#include<bits/stdc++.h>
#define ll int
#define rg register
#define rll rg ll
#define pll pair<ll,ll>
#define maxn 3001
#define put_ putchar(' ')
#define putn putchar('\n')
using namespace std;
inline ll read()
{
rg bool f=0;rll x=0;rg char ch=getchar();while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^'0'),ch=getchar(); return f?-x:x;
}
inline void write(rll x) { if(x<0) putchar('-'),x=-x; if(x>9) write(x/10);putchar(x%10|'0'); }
ll n,a[maxn],g,hz[maxn],ans=0x7fffffff;
inline ll gcd(rll x,rll y) { if(!y) return x; return gcd(y,x%y); }
inline void dfs(rll x,rll num,rll gd)
{
if(gd==g) { ans=min(ans,x);return; } if(x>=min(ans,9)||gd<g||num==n+1||gcd(gd,hz[num+1])>g) return;
for(rll i=num+1;i<=n;i++) { dfs(x+1,i,gcd(gd,a[i])); }
}
int main()
{
freopen("weights.in","r",stdin); freopen("weights.out","w",stdout);
// for(rll i=25;;i+=25) if(!((15+i)%9)) {cout<<i/25<<' '<<(15+i)/9<<endl;break;}
n=read(); for(rll i=1;i<=n;i++) a[i]=read(); random_shuffle(a+1,a+n+1); if(a[1]==1) { putchar('1'); return 0; }
g=a[1]; for(rll i=2;i<=n;i++) g=gcd(g,a[i]);
hz[n]=a[n]; for(rll i=n-1;i;i--) hz[i]=gcd(hz[i+1],a[i]);
for(rll i=1;i<=n;i++) dfs(1,i,a[i]); write(ans);
return 0;
}
支配数据
一看区间修改查询肯定是线段树. 但是总的大小是 1e9,硬上肯定是不行地.
发现修改的区间最多只有 1e6 个,可以把修改离散化一下,将修改和查询的点进行处理. 存一下这些区间的端点,然后排序一下. 把每两个端点生成的区间当成一个节点放到线段树里.
但是这样不对. 如果有修改的区间重叠,这样会算重. 所以可以把有效的那些点单独作为一个区间,中间夹着的部分作为一个区间.
在预处理每个区间的权值的时候,直接暴力显然会 TLE,所以用一个 ST 表查就可以了.
这样并不需要动态开点,只用一棵查最小值的线段树就可以了.
点击查看代码
#include<bits/stdc++.h>
#define ll int
#define rg register
#define rll rg ll
#define pll pair<ll,ll>
#define maxn 400001
#define put_ putchar(' ')
#define putn putchar('\n')
using namespace std;
inline ll read()
{
rg bool f=0;rll x=0;rg char ch=getchar();while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^'0'),ch=getchar(); return f?-x:x;
}
inline void write(rll x) { if(x<0) putchar('-'),x=-x; if(x>9) write(x/10);putchar(x%10|'0'); }
struct node { ll op,l,r,x; }a[maxn];
ll n,k,m,q,mn=0x7fffffff,b[maxn],id[maxn<<2],len,id1[maxn<<2],len1,ans[maxn],posl[maxn],posr[maxn],cnt;
class st
{
private:
ll mn[maxn][21];
public:
inline void init(rll n)
{
for(rll i=1;i<=n;i++) mn[i][0]=b[i];
for(rll j=1;j<=20;j++) for(rll i=1;i+(1<<j)-1<=n;i++) mn[i][j]=min(mn[i][j-1],mn[i+(1<<(j-1))][j-1]);
}
inline ll query(rll l,rll r) { rll k=log2(r-l+1); return min(mn[l][k],mn[r-(1<<k)+1][k]); }
}s;
struct tree
{
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
ll v,tag;
}t[maxn<<4];
#define pushup(rt) t[rt].v=min(t[ls(rt)].v,t[rs(rt)].v)
inline void pushdown(rll rt)
{
if(t[rt].tag) t[ls(rt)].v=t[rt].tag,t[rs(rt)].v=t[rt].tag,
t[ls(rt)].tag=t[rt].tag,t[rs(rt)].tag=t[rt].tag,t[rt].tag=0;
}
inline ll getmn(rll x)
{
rll l=posl[x],r=posr[x],ans=0x7fffffff; if(r-l+1>=n) return mn; l=(l-1)%n+1,r=(r-1)%n+1;
if(l>r) return min(s.query(1,r),s.query(l,n)); return s.query(l,r);
}
inline void build(rll rt,rll l,rll r)
{
if(l==r) { t[rt].v=getmn(l); /*cout<<posl[l]<<' '<<posr[l]<<' '<<t[rt].v<<endl;*/ return; } rll mid=(l+r)>>1;
build(ls(rt),l,mid); build(rs(rt),mid+1,r); pushup(rt);
}
inline void upd(rll rt,rll l,rll r,rll x,rll y,rll v)
{
if(x<=l&&r<=y) { t[rt].v=t[rt].tag=v;return; } pushdown(rt); rll mid=(l+r)>>1;
if(x<=mid) upd(ls(rt),l,mid,x,y,v); if(y>mid) upd(rs(rt),mid+1,r,x,y,v); pushup(rt);
}
inline ll query(rll rt,rll l,rll r,rll x,rll y)
{
if(x<=l&&r<=y) return t[rt].v; pushdown(rt); rll mid=(l+r)>>1,ans=0x7fffffff;
if(x<=mid) ans=query(ls(rt),l,mid,x,y); if(y>mid) ans=min(ans,query(rs(rt),mid+1,r,x,y)); return ans;
}
int main()
{
freopen("data.in","r",stdin); freopen("data.out","w",stdout);
// freopen("in.txt","r",stdin); freopen("out.txt","w",stdout);
n=read();k=read();m=n*k; for(rll i=1;i<=n;i++) mn=min(mn,b[i]=read()); q=read(); fprintf(stderr,"%lld %lld %lld\n",n,k,m);
s.init(n);
for(rll i=1;i<=q;i++) switch(a[i].op=read())
{
case 1:id[++len]=a[i].l=read(); id[++len]=a[i].r=read(); a[i].x=read(); break;
case 2:id[++len]=a[i].l=read(); id[++len]=a[i].r=read(); break;
}
id[++len]=1,id[++len]=m; sort(id+1,id+len+1); len=unique(id+1,id+len+1)-id-1;// cout<<len<<endl;
// sort(id2+1,id2+len2+1); len2=unique(id2+1,id2+len2+1)-id2-1;
// for(rll i=1;i<=len2;i++) id[++len]=id2[i]; sort(id+1,id+len+1);// cout<<len<<endl;
for(rll i=1;i<len;i++) { posl[++cnt]=id[i];posr[cnt]=id[i]; if(id[i+1]-id[i]>1) posl[++cnt]=id[i]+1,posr[cnt]=id[i+1]-1; }
posl[++cnt]=id[len];posr[cnt]=id[len];
fprintf(stderr,"%d\n",cnt);
for(rll i=1;i<=q;i++) a[i].l=lower_bound(posl+1,posl+cnt+1,a[i].l)-posl,a[i].r=lower_bound(posr+1,posr+cnt+1,a[i].r)-posr;
build(1,1,cnt); for(rll i=1;i<=q;i++) switch(a[i].op)
{
case 1:upd(1,1,cnt,a[i].l,a[i].r,a[i].x);break;
case 2:write(query(1,1,cnt,a[i].l,a[i].r));putn;break;
}
return 0;
}
信息学的尽头
基环树模板题,没啥好说的.
点击查看代码
#include<bits/stdc++.h>
#define ll long long
#define rg register
#define rll rg ll
#define pll pair<ll,ll>
#define maxn 200001
#define put_ putchar(' ')
#define putn putchar('\n')
using namespace std;
inline ll read()
{
rg bool f=0;rll x=0;rg char ch=getchar();while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^'0'),ch=getchar(); return f?-x:x;
}
inline void write(rll x) { if(x<0) putchar('-'),x=-x; if(x>9) write(x/10);putchar(x%10|'0'); }
ll n,cnt,t,s,ans[maxn],a[maxn<<2],b[maxn<<2],st,len,sz[maxn],tot[maxn],sum[maxn<<1];
vector<pll> g[maxn];
bool fl[maxn];
inline bool dfs1(rll x,rll fa)
{
fl[x]=1; for(rll i=0;i<g[x].size();i++)
{
rll to=g[x][i].first; if(to==fa) continue;
if(fl[to]) { st=to; a[++cnt]=x; b[cnt]=g[x][i].second; len+=g[x][i].second; return 1; }
if(dfs1(to,x)){ a[++cnt]=x; b[cnt]=g[x][i].second; len+=g[x][i].second; return x^st; }
}
return fl[x]=0;
}
inline void dfs2(rll x,rll fa)
{
for(rll i=0;i<g[x].size();i++)
{
rll to=g[x][i].first; if(to==fa||fl[to]) continue;
dfs2(to,x); tot[x]+=tot[to]+sz[to]*g[x][i].second; sz[x]+=sz[to];
}
sz[x]++;
}
inline void dfs3(rll x,rll fa)
{
for(rll i=0;i<g[x].size();i++)
{
rll to=g[x][i].first; if(to==fa||fl[to]) continue;
ans[to]=ans[x]+(n-sz[to])*g[x][i].second-sz[to]*g[x][i].second; dfs3(to,x);
}
}
int main()
{
freopen("end.in","r",stdin); freopen("end.out","w",stdout);
n=read(); for(rll i=1,u,v,w;i<=n;i++) u=read(),v=read(),w=read(),g[u].push_back((pll) { v,w }),g[v].push_back((pll) { u,w });
dfs1(1,0); for(rll i=1;i<=cnt<<1;i++) a[i+cnt]=a[i],b[i+cnt]=b[i]; for(rll i=1;i<=cnt<<1;i++) sum[i]=sum[i-1]+b[i];
for(rll i=1;i<=cnt;i++) fl[a[i]]=1; for(rll i=1;i<=cnt;i++) dfs2(a[i],0);
for(rll i=2;i<=cnt+1;i++) t+=tot[a[i]]+min(len-(sum[cnt+1]-sum[i]),sum[cnt+1]-sum[i])*sz[a[i]];
for(rll i=2;i<=cnt+1;i++) if(sum[cnt+1]-sum[i]<=len-(sum[cnt+1]-sum[i])) { st=i;break; } for(rll i=st;i<=cnt+1;i++) s+=sz[a[i]];
for(rll i=cnt+1;i<=cnt<<1;i++)
{
if(i^cnt+1)
{
t+=s*b[i]; t-=(n-s)*b[i]; s+=sz[a[i]];
while(sum[i]-sum[st]>=len-(sum[i]-sum[st]))
s-=sz[a[st]],t+=((len-(sum[i]-sum[st]))-(sum[i]-sum[st]))*sz[a[st]],st++;
}
ans[a[i]]=t;
}
for(rll i=1;i<=cnt;i++) dfs3(a[i],0); for(rll i=1;i<=n;i++) write(ans[i]),put_;
return 0;
}
球对称薛定谔方程
设 dp[i][j][k] 表示当前长度为 i、当前位置放 j、后面还有 k 个位置没有决定放的方案数.
转移:
-
dp[i][j][k - 1] += dp[i][j][k],不再往当前位置放 j,后面决定放的位置减一;
-
dp[i][j + 1][i] += dp[i][j][k],没有可以放的位置了,决定放的位置减小到 i;
-
dp[i + 1][j][k] += dp[i][j][k] × (k + 1):在当前位置放一个 j,k 不变是因为 j 的后面还可以再放.
初始状态 dp[1][i][0] = 1 (i ∈ [1 , k]),
答案即为 dp[n][k][0].
点击查看代码
#include<bits/stdc++.h>
#define ll long long
#define rg register
#define rll rg ll
#define pll pair<ll,ll>
#define maxn 302
#define put_ putchar(' ')
#define putn putchar('\n')
using namespace std;
inline ll read()
{
rg bool f=0;rll x=0;rg char ch=getchar();while(ch<'0'||ch>'9') f|=ch=='-',ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^'0'),ch=getchar(); return f?-x:x;
}
inline void write(rll x) { if(x<0) putchar('-'),x=-x; if(x>9) write(x/10);putchar(x%10|'0'); }
ll n,k,m,ans,dp[maxn][maxn][maxn];
int main()
{
freopen("seq.in","r",stdin); freopen("seq.out","w",stdout);
n=read();k=read();m=read(); for(rll i=1;i<=k;i++) dp[1][i][0]=1;
for(rll i=1;i<=n;i++) for(rll j=1;j<=k;j++)
{
for(rll k=i;~k;k--) { if(k) (dp[i][j][k-1]+=dp[i][j][k])%=m; (dp[i+1][j][k]+=(k+1)*dp[i][j][k])%=m; }
(dp[i][j+1][i]+=dp[i][j][0])%=m;
}
write(dp[n][k][0]);
return 0;
}
--END--

浙公网安备 33010602011771号
我的博客: 𝟷𝙻𝚒𝚞
本文链接: https://www.cnblogs.com/1Liu/p/16886706.html
版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!