Codeforces Round #818 (Div. 2)

Codeforces Round #818 (Div. 2)

赛时

A B C D
7min 38min 57min 100min
+1 +1

基准分:1834
排名:rk736
rating:14391556

1100 卡半小时就 NM 离谱。
哦对着看错的题面搓了二十分钟啊,没事了。
为什么有人 D 会不加取模啊……
为什么 F 连着两次网络流啊……

A

CF1717A Madoka and Strange Thoughts

800
对于 x,答案只有可能是 (x,2x)(x,3x)
所以输出 n+2(n2+n3) 即可。
时间复杂度:O(1)

void work(){cin>>n,cout<<n+(n/2)*2+(n/3)*2<<'\n';}

提交记录

B

CF1717B Madoka and Underground Competitions

1100
就稍微倒退一下,循环每行要标记的的点即可。
反正就处理一下循环条件就行了,毕竟是 B 题。
时间复杂度:O(nm)

#define L(i,j,k) for(int i=(j);i<=(k);i++)
void work(){
  cin>>n>>k>>x>>y;
  int t=y%k;
  L(i,1,n) L(j,1,n) s[i][j]='.';
  L(i,0,n-1)
    for(int j=(t+i)%k;j<=n;j+=k)
      s[X(x+i)][j]='X';
  L(i,1,n){L(j,1,n) cout<<s[i][j];cout<<'\n';}
}

提交记录

C

CF1717C Madoka and Formal Statement

1300
手搓下样例就大概能知道些规律。
首先,如果出现 ai>bi 的情况就直接判为无解。
对于一个数 ai,如果要变成 bi,要么 ai 本来就和 bi 相等,否则就是通过 ai+1 增值。
显然,ai 最大只能增大到 bi+1modn+1,直接判断即可。
时间复杂度:O(n)

#define X(i) (i>n?i-n:(i<=0?i+n:i))
#define L(i,j,k) for(int i=(j);i<=(k);i++)
void work(){
  cin>>n;L(i,1,n) cin>>a[i];L(i,1,n) cin>>b[i];
  bool f=0;L(i,1,n) if(a[i]>b[i]) f=1;
  if(f) return cout<<"NO"<<'\n',void();
  L(i,1,n) if(b[i]>b[X(i+1)]+1&&a[i]!=b[i]) 
    return cout<<"NO"<<'\n',void();
  cout<<"YES"<<'\n';
}

提交记录

D

文字表述参考了 CF 上的讨论,这与我赛时做法基本一致,但得出思路的过程不同且其更具有参考价值,所以主要记录的是以上做法。

CF1717D Madoka and The Corruption Scheme

1900
留个坑:因为答案等于 [xk](1+x)n1x 所以可以用 FFT 爆艹什么鬼

问题是在满二叉树上讨论的。
x 为当前 k 下,能保证无法获胜的人的个数,那么答案就是 2nx

然后本人的赛时做法就是找个 n=4 的状态手摸,发现了规律,然后写上去过了无比草率

尝试写个爆搜:

const int mod=1e9+7;
int ksm(int a,int b){
  int s=1;
  while(b){
    if(b&1) (s*=a)%=mod;
    (a*=a)%=mod;b>>=1;
  }return s;
}int solve(int n,int k){
  if(n<k||n<0) return 0;
  if(!k) return ksm(2,n);
  else return solve(n-1,k)+solve(n-1,k-1);
}

学过组合数学的话,可能会感觉上面的式子有点熟悉。

其实对于在二叉树上进行拓展的状态可以类比到杨辉三角上。
每次操作可以新增加的可控人数就是第 n 层的当前位的值。

或者,递推 n 的值,设之前一个推导的数 m,其之间的差为 (nm1k) 次。
因为每次的选择都会被确定,也不难得到上述式子。

所以,预处理组合数,随便选一种上述思路模拟即可。
别忘了加取模

时间复杂度:O(n)

#include <bits/stdc++.h>
#define int long long
#define L(i,j,k) for(int i=(j);i<=(k);i++)
const int N=1e5+100,mod=1e9+7;
int n,k;
int d[N],jc[N],inv[N];
void init(){
  d[0]=d[2]=1,d[1]=0;L(i,3,N-10) d[i]=(i-1)*(d[i-1]+d[i-2])%mod;
  jc[0]=1;L(i,1,N-10) jc[i]=jc[i-1]*i%mod;
  inv[1]=1;L(i,2,N-10) inv[i]=(mod-mod/i)*inv[mod%i]%mod;
  inv[0]=1;L(i,1,N-10) inv[i]=inv[i-1]*inv[i]%mod;
}int C(int x,int y){return (jc[x]*inv[y]%mod*inv[x-y]%mod);}
int ksm(int a,int b){
  int s=1;
  while(b){
    if(b&1) (s*=a)%=mod;
    (a*=a)%=mod;b>>=1;
  }return s;
}void work(){
  cin>>n>>k;int sum=0;
  L(i,0,(min(n,k))) 
    (sum+=C(n,i))%=mod;
  cout<<sum;
}void work(){
  int ans=ksm(2,n);
  L(i,0,n) (ans-=ksm(2,i),C(n-i-1,k)-mod)%=mod;
  cout<<ans;
}signed main(){init();work();}

E

参考资料:OMG_wc(幻想家协会会长)的视频题解

CF1717E Madoka and The Best University

2200

首先考虑暴力做法,直接枚举 a,b,然后 c=nab,求出值后直接相加即可。时间复杂度:O(n2log2n)

换个思路,每次枚举 c 的值,此时 a+b=nc,很明显我们不能直接枚举 a,b 的值,那就直接枚举 gcd(a,b) 的值。
x=a+b,每次枚举的数是 t,则 t|x 并且 (at,bt)=1,辗转相除法推一步就可知 (at,xt)=1

此时 a 的取值个数也就是 a,b 的可取对数不难看出是 ϕ(xt),那就可以预处理出 ϕ(i) 的值,然后做到每次 O(1) 查询。

此时的时间复杂度为:O(n) 枚举 c 的值,O(n) 枚举 c 的所有因数,ϕ 的值可以 O(n)O(nlog2(log2n)) 预处理出来。无耻宣博

时间复杂度:O(nnlog2n)

#define L(i,j,k) for(int (i)=(j);i<=(k);(i)++)
#define ll(i,j,k,l) for(int (i)=(j);i<=(k);(i)+=(l))
const int N=1e5+100;int n,p[N];
int lcm(int x,int y){return x*y/__gcd(x,y);}
void work(){
  cin>>n;int ans=0;L(i,1,n) p[i]=i;
  L(i,2,n) if(p[i]==i)
    ll(j,i,n,i) p[j]=p[j]/i*(i-1);
  L(i,1,n-2){
    int t=n-i;
    L(j,1,sqrt(t)) if(!(t%j)){
      (ans+=lcm(i,j)*p[t/j])%=mod;
      if(j!=1&&j!=t/j) (ans+=lcm(i,t/j)*p[j])%=mod;
    }
  }cout<<ans;
}

CF1717E Madoka and The Best University

2500
网络流。

posted @   AIskeleton  阅读(22)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
点击右上角即可分享
微信分享提示