锦标赛问题
CF1717D
首先,编号之间没有区别,所以我们不妨设布置比赛的时候顺序布置,并让每场比赛中编号最小的选手获胜,如下图:
这样的比赛包含一个美妙的性质,其实是可以猜出来的:
如果把每个人的编号都 ,变成 ,然后转化为二进制,那么从右到左第 位是 就表示:这个选手所在的“ 个选手组成的区域”中的胜者在第 轮会赢,否则会输。
比如 ,那么原来场上的 号选手在第一轮会赢,在第二轮会输,并且在第三轮中 号选手所在的 区域中胜者 号会赢。
这样就很容易操作了,发现把一个人保送到冠军的过程就是修改每一个 的位置,让他能赢。这样的话,只要 的个数不超过 ,那么就可以做到。
因此题意等价于:求 里 的 的个数,也就等于 。这个东西直接算算就好了。
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define f(i, a, b) for(int i = (a); i <= (b); i++)
#define cl(i, n) i.clear(),i.resize(n);
#define endl '\n'
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
const int inf = 1e9;
const int mod = 1e9 + 7;
int qpow(int x, int k) {
int ans = 1;
while(k) {
if(k & 1) ans = ans*x%mod;
x=x*x%mod;
k>>=1;
}
return ans;
}
int prod[100010], inv[100010];
int c(int n,int m){
return prod[n]*inv[n-m]%mod*inv[m]%mod;
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(NULL);
cout.tie(NULL);
time_t start = clock();
//think twice,code once.
//think once,debug forever.
int n, k; cin >> n >> k;
if(k > n) k = n;
prod[0]=inv[0]=1;
f(i, 1, n) {
prod[i]=prod[i-1]*i%mod;
inv[i]=qpow(prod[i],mod-2);
}
int ans = 0;
f(i,0,k){
ans+=c(n,i);
ans%=mod;
}
cout << ans << endl;
time_t finish = clock();
//cout << "time used:" << (finish-start) * 1.0 / CLOCKS_PER_SEC <<"s"<< endl;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具