来自aakennes的新年祝福
组题人: @aakennes
\(A\) P888. 字符串会上树 \(AC\)
- 基础字符串。
点击查看代码
string s,t="",w="";
map<string,string>f;
int main()
{
// #define Isaac
#ifdef Isaacfreopen("in.in","r",stdin);freopen("out.out","w",stdout);
#endifint n,q,i;cin>>n>>q>>s;for(i=0;i<=n-1;i++){if(s[i]=='&') {f[t]=w;t="";}else if(s[i]=='=') w="";else if('0'<=s[i]&&s[i]<='9') w+=s[i];else t+=s[i];}if(t!="") f[t]=w;for(i=1;i<=q;i++){cin>>s;if(f.find(s)==f.end()) cout<<"Does not exist."<<endl;else cout<<f[s]<<endl;}return 0;
}
\(B\) P889. 挖宝石 \(AC\)
-
背包循环移位转移。
点击查看代码
bool f[2][3010]; int main() { // #define Isaac #ifdef Isaacfreopen("in.in","r",stdin);freopen("out.out","w",stdout); #endifll n,k,x,i,j;cin>>n>>k;for(i=1;i<=n;i++){cin>>x;x%=k;for(j=0;j<=x-1;j++) f[i&1][j]=f[(i-1)&1][j]|f[(i-1)&1][(j-x+k)%k];for(j=x;j<=k-1;j++) f[i&1][j]=f[(i-1)&1][j]|f[(i-1)&1][j-x];f[i&1][x]=1;if(f[i&1][0]==1){cout<<"Yes"<<endl;return 0;}}cout<<"No"<<endl;return 0; }
\(C\) P890. 电梯系统 \(AC\)
-
手摸样例,得到一种构造方式形如
1->2->3->4->5->6->7 1---->3---->5---->7 1------->4---->6 1---------->5 1------------->6 1---------------->72---->4------->72------->52---------->62------------->73------>63------>7
-
可知 \(\sum\limits_{i=1}^{n}\max(0,n-(2i-1))\) 即为所求。
点击查看代码
int main() { // #define Isaac #ifdef Isaacfreopen("in.in","r",stdin);freopen("out.out","w",stdout); #endifll n,ans=0,i;cin>>n;for(i=1;i<=n;i++){if(2*i-1<=n) ans+=n-(2*i-1);}cout<<ans<<endl;return 0; }
\(D\) P891. 打游戏 \(AC\)
-
和求树的直径一样做即可。
点击查看代码
struct node {ll nxt,to,w; }e[200010]; ll head[100010],a[100010],f[100010],g[100010],len,cnt=0; void add(ll u,ll v,ll w) {cnt++;e[cnt].nxt=head[u];e[cnt].to=v;e[cnt].w=w;head[u]=cnt; } void dfs(ll x,ll fa) {for(ll i=head[x];i!=0;i=e[i].nxt){if(e[i].to!=fa){dfs(e[i].to,x);if(f[e[i].to]-e[i].w>f[x]){g[x]=f[x];f[x]=f[e[i].to]-e[i].w;}else{g[x]=max(g[x],f[e[i].to]-e[i].w);}}}f[x]+=a[x];len=max(len,f[x]+g[x]); } int main() { // #define Isaac #ifdef Isaacfreopen("in.in","r",stdin);freopen("out.out","w",stdout); #endifll n,u,v,w,i;cin>>n;for(i=1;i<=n;i++) cin>>a[i];for(i=1;i<=n-1;i++){cin>>u>>v>>w;add(u,v,w); add(v,u,w);}dfs(1,0);cout<<len<<endl;return 0; }
\(E\) P892. 魔法水晶 \(AC\)
-
考虑建出最短路 \(DAG\) 后补全成原图并计数。
点击查看代码
const ll p=998244353; ll a[200010],cnt[200010]; ll qpow(ll a,ll b,ll p) {ll ans=1;while(b){if(b&1) ans=ans*a%p;b>>=1;a=a*a%p;}return ans; } int main() { // #define Isaac #ifdef Isaacfreopen("in.in","r",stdin);freopen("out.out","w",stdout); #endifll n,ans=1,i;cin>>n;for(i=1;i<=n;i++) {cin>>a[i];cnt[a[i]]++;}for(i=1;i<=n-1&&cnt[i]!=0;i++) ans=ans*qpow((qpow(2,cnt[i-1],p)-1+p)%p,cnt[i],p)%p*qpow(2,cnt[i]*(cnt[i]-1)/2,p)%p;for(;i<=n-1;i++) if(cnt[i]!=0) ans=0;cout<<ans<<endl;return 0; }
\(F\) P893. 随机数序列
-
根据左右移位时不变的位置顺次求出其他位置。
点击查看代码
uint a[200010],t[50]; pair<uint,uint>c[200010]; uint random(uint& seed) {seed ^= (seed << 16);seed ^= (seed >> 5);seed ^= (seed << 1);return seed; } uint rev(uint x) {for(int i=31;i>=0;i--) t[i]=(x>>i)&1;for(int i=1;i<=31;i++) t[i]^=t[i-1];for(int i=26;i>=0;i--) t[i]^=t[i+5];for(int i=16;i<=31;i++) t[i]^=t[i-16];x=0;for(int i=31;i>=0;i--) x=(x<<1)|t[i];return x; } int main() { // #define Isaac #ifdef Isaacfreopen("in.in","r",stdin);freopen("out.out","w",stdout); #endifint n,i;uint seed;cin>>n;for(i=1;i<=n;i++) cin>>c[i].first>>c[i].second;sort(c+1,c+1+n);seed=a[c[1].first]=c[1].second;for(i=c[1].first+1;i<=200000;i++) a[i]=random(seed);for(i=2;i<=n;i++){if(a[c[i].first]!=c[i].second){cout<<"no"<<endl;return 0;}}seed=c[1].second;for(i=1;i<=c[1].first;i++) seed=rev(seed);cout<<seed<<endl;return 0; }
\(G\) P894. 线段树改造 \(AC\)
-
观察到循环移位 \(i \bigotimes j=(i+j+1) \bmod 4\) ,询问时的 \(+1\) 提出来最后再加。
点击查看代码
int a[200010]; struct SMT {struct SegmentTree{int len,sum,lazy;}tree[800010];#define lson(rt) (rt<<1)#define rson(rt) (rt<<1|1)void pushup(int rt){tree[rt].sum=(tree[lson(rt)].sum+tree[rson(rt)].sum)%4;}void build(int rt,int l,int r){tree[rt].len=r-l+1;if(l==r){tree[rt].sum=a[l];return;}int mid=(l+r)/2;build(lson(rt),l,mid);build(rson(rt),mid+1,r);pushup(rt);}void pushlazy(int rt,int lazy){tree[rt].lazy=(tree[rt].lazy+lazy)%4;tree[rt].sum=(tree[rt].sum+lazy*tree[rt].len)%4;}void pushdown(int rt){pushlazy(lson(rt),tree[rt].lazy);pushlazy(rson(rt),tree[rt].lazy);tree[rt].lazy=0;}void update(int rt,int l,int r,int x,int y,int val){if(x<=l&&r<=y){pushlazy(rt,val);return;}pushdown(rt);int mid=(l+r)/2;if(x<=mid) update(lson(rt),l,mid,x,y,val);if(y>mid) update(rson(rt),mid+1,r,x,y,val);pushup(rt);}int query(int rt,int l,int r,int x,int y){if(x<=l&&r<=y) return tree[rt].sum;pushdown(rt);int mid=(l+r)/2;if(y<=mid) return query(lson(rt),l,mid,x,y);if(x>mid) return query(rson(rt),mid+1,r,x,y);return (query(lson(rt),l,mid,x,y)+query(rson(rt),mid+1,r,x,y))%4;} }T; int main() { // #define Isaac #ifdef Isaacfreopen("in.in","r",stdin);freopen("out.out","w",stdout); #endifint n,m,pd,l,r,x,i;cin>>n>>m;for(i=1;i<=n;i++) cin>>a[i];T.build(1,1,n);for(i=1;i<=m;i++){cin>>pd>>l>>r;if(pd==1){cin>>x;T.update(1,1,n,l,r,x+1);}else{cout<<(r-l+T.query(1,1,n,l,r))%4<<endl;}}return 0; }
\(H\) P895. 赌博 \(AC\)
-
题目要求找到 \((x+\frac{f(f+1)}{2}) \bmod n=0\) 的最小正整数解,观察到有用的 \(f<n\) 且 \(\sum n \le 2 \times 10^{5}\) ,枚举即可。
点击查看代码
int main() { // #define Isaac #ifdef Isaacfreopen("in.in","r",stdin);freopen("out.out","w",stdout); #endifll t,n,x,p,r,flag,i,j;cin>>t;for(j=1;j<=t;j++){cin>>n>>x>>p;flag=0;for(i=1;i<=p&&i<=n-1;i++){if((i*(i+1)/2%n+x)%n==0){flag=1;cout<<"Yes"<<endl;break;}}if(flag==0) cout<<"No"<<endl;}return 0; }
\(I\) P896. 魔法水晶2
\(J\) P897. 对战
-
原题: NOIP2024加赛1 T2 HZTG2081. 排列
-
稍微卡卡常。
点击查看代码
const int p=998244353; int C[7010][7010],f[2][2][7010][20]; int qadd(int a,int b) {return a+b>=p?a+b-p:a+b; } int main() { // #define Isaac #ifdef Isaacfreopen("in.in","r",stdin);freopen("out.out","w",stdout); #endifint n,m,tmp,tmp1,tmp2,i,j,k;cin>>n>>m;if(1.0*m>log2(n)+5.0){cout<<0<<endl;}else{C[0][0]=C[1][0]=C[1][1]=1;for(i=2;i<=n;i++){C[i][0]=1;for(j=1;j<=i;j++){C[i][j]=(C[i-1][j-1]+C[i-1][j])%p;}}for(i=0;i<=m;i++){f[0][0][0][i]=f[0][1][0][i]=f[1][0][0][i]=f[1][1][0][i]=1;}for(i=1;i<=n;i++){for(j=1;j<=m;j++){for(k=1;k<=i;k++){tmp=C[i-1][k-1];f[0][0][i][j]=qadd(f[0][0][i][j],(1ll*f[0][1][k-1][j]*f[1][0][i-k][j]%p)*tmp%p);f[1][0][i][j]=qadd(f[1][0][i][j],(1ll*f[1][1][k-1][j-1]*f[1][0][i-k][j]%p)*tmp%p);f[0][1][i][j]=qadd(f[0][1][i][j],(1ll*f[0][1][k-1][j]*f[1][1][i-k][j-1]%p)*tmp%p);tmp1=(f[1][1][k-1][j]-f[1][1][k-1][j-1]+p)%p;tmp2=(f[1][1][i-k][j]-f[1][1][i-k][j-1]+p)%p;f[1][1][i][j]=qadd(f[1][1][i][j],((1ll*f[1][1][k-1][j]*f[1][1][i-k][j]%p-1ll*tmp1*tmp2%p+p)%p)*tmp%p);}}}cout<<(f[0][0][n][m]-f[0][0][n][m-1]+p)%p<<endl;}return 0; }
\(K\) P898. 交通网络
\(L\) P899. 疯狂的矩阵
\(M\) P900. 超级计算机
\(N\) P901. 线段树改造2
-
既然已经限制了 \(\bigotimes\) 具有结合律,线段树直接维护即可。
-
难点在于中缀表达式求值,建议先去写 luogu P10473 表达式计算4 。
点击查看代码
const int p=998244353; int a[200010],len; char s[60]; stack<int>s1; stack<char>s2; int val(char x) {if(x=='(') return 0;if(x=='+'||x=='-') return 1;if(x=='*') return 2;return -1; } void work() { int a=s1.top(); s1.pop();int b=s1.top(); s1.pop();char c=s2.top(); s2.pop();if(c=='+') s1.push((b+a)%p);if(c=='-') s1.push((b-a+p)%p);if(c=='*') s1.push(1ll*b*a%p); } int ask(int x,int y) {int tmp=0,flag=0;for(int i=1;i<=len;i++){if(('0'<=s[i]&&s[i]<='9')||s[i]=='a'||s[i]=='b') {if('0'<=s[i]&&s[i]<='9') tmp=(tmp*10%p+s[i]-'0')%p;else tmp=(s[i]=='a')?x:y;flag=1;if(i==len) s1.push(tmp);}else {if(flag==1){s1.push(tmp);tmp=flag=0;}if(s[i]=='(') s2.push(s[i]);else if(s[i]==')') {while(s2.top()!='(') work();s2.pop();}else{while(s2.empty()==0&&val(s2.top())>=val(s[i])) work();s2.push(s[i]);}}if(i==len) while(s2.empty()==0) work();}return s1.top(); } struct SMT {struct SegmentTree{int sum;}tree[800010];#define lson(rt) (rt<<1)#define rson(rt) (rt<<1|1)void pushup(int rt){tree[rt].sum=ask(tree[lson(rt)].sum,tree[rson(rt)].sum);}void build(int rt,int l,int r){if(l==r){tree[rt].sum=a[l];return;}int mid=(l+r)/2;build(lson(rt),l,mid);build(rson(rt),mid+1,r);pushup(rt);}void update(int rt,int l,int r,int pos,int val){if(l==r){tree[rt].sum=ask(tree[rt].sum,val);return;}int mid=(l+r)/2;if(pos<=mid) update(lson(rt),l,mid,pos,val);else update(rson(rt),mid+1,r,pos,val);pushup(rt);}int query(int rt,int l,int r,int x,int y){if(x<=l&&r<=y) return tree[rt].sum;int mid=(l+r)/2;if(y<=mid) return query(lson(rt),l,mid,x,y);if(x>mid) return query(rson(rt),mid+1,r,x,y);return ask(query(lson(rt),l,mid,x,y),query(rson(rt),mid+1,r,x,y));} }T; int main() { // #define Isaac #ifdef Isaacfreopen("in.in","r",stdin);freopen("out.out","w",stdout); #endifint n,m,pd,l,r,i;cin>>(s+1)>>n>>m;len=strlen(s+1);for(i=1;i<=n;i++) cin>>a[i];T.build(1,1,n);for(i=1;i<=m;i++){cin>>pd>>l>>r;if(pd==1){T.update(1,1,n,l,r);}else{cout<<T.query(1,1,n,l,r)<<endl;}}return 0; }
\(O\) P902. 水果店
- 原题: luogu P4655 [CEOI 2017] Building Bridges
- 题解
总结
- 开题顺序: \(DAGBCEH\)
- \(F\) 题罚坐两小时推逆运算没推出来。
后记
-
\(H\) 数据范围分成了两部分,一半在输入格式里,一半在提升里。
-
\(O\) 因之前基本都写过遂找 \(huge\) 删了,题目背景留作存档。