比赛链接:https://codeforces.com/contest/1747
题解:
AB
水题
// by SkyRainWind
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#define mpr make_pair
#define debug() cerr<<"Yoshino\n"
#define rep(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define pii pair<int,int>
using namespace std;
typedef long long LL;
const int inf = 1e9, INF = 0x3f3f3f3f,maxn=2e5+5;
int n,a[maxn];
void solve(){
LL s=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]), s+=a[i];
printf("%lld\n",abs(s));
}
signed main(){
// |a|-|S-a|
int te;scanf("%d",&te);
while(te --)solve();
return 0;
}
// by SkyRainWind
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#define mpr make_pair
#define debug() cerr<<"Yoshino\n"
#define rep(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define pii pair<int,int>
using namespace std;
typedef long long LL;
const int inf = 1e9, INF = 0x3f3f3f3f;
//BANBANBAN
//BANBANBANBANBANBAN
//BANBANBANBANBANBANBANBANBAN
//BAN
//BANBANBANBANBANBANBAN
//BAN BAN BAN BAN BAN BAN BAN BAN BAN BAN
//BAN BAN BAN BAN BAN 5 3
// BAN BAN BAN BAN BAN BAN BAN BAN 8 5
//BNNBAABANBAN
int n;
void solve(){
scanf("%d",&n);
int t=1,cnt=0;
for(int i=n*3;;i-=3){
if(t >= i)break;
++cnt;
// printf("%d %d\n",t,i);
t += 3;
}
printf("%d\n",cnt);
t=1;
for(int i=n*3;;i-=3){
if(t >= i)break;
++cnt;
printf("%d %d\n",t,i);
t += 3;
}
}
signed main(){
int te;scanf("%d",&te);
while(te--){solve();
}
return 0;
}
C
当前选手输:0 [a2 ... an]
什么情况能推到出上面的局面?a1 [a2 .. 0 .. an] 必胜 ;因此 1 [a2 .. an](且ai>=1,否则就是前面一种情况)必输
什么时候能有1 [a2 .. an]情况?我们发现这就是一个归纳的过程,最后结论就是a2..an如果有一个<a1就剩否则输
// by SkyRainWind
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#define mpr make_pair
#define debug() cerr<<"Yoshino\n"
#define rep(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define pii pair<int,int>
using namespace std;
typedef long long LL;
const int inf = 1e9, INF = 0x3f3f3f3f;
int n,a[200005];
signed main(){
int te;scanf("%d",&te);
while(te--){
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
int fg=0;
for(int i=2;i<=n;i++)
if(a[i] < a[1])fg = 1;
puts(fg ? "Alice" : "Bob");
}
return 0;
}
D
如果区间长度是奇数,结论是平凡的:-1/0/1
区间长度是偶数?答案一定不超过2!
证明?首先答案一定不可能是3(3个奇数加起来不是偶数)
如果答案是4?那我取3个和1个奇数不就变成了答案2
注意答案可能是1:a[l]==0 || a[r] == 0
于是就把前缀异或和按位置的奇偶性存一下,需要用map把异或和离散化
此题卡常!
// by SkyRainWind
#include <cstdio>
#include <vector>
#include <cstring>
#include <map>
#include <iostream>
#include <set>
#include <algorithm>
#define mpr make_pair
#define debug() cerr<<"Yoshino\n"
#define rep(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define pii pair<int,int>
using namespace std;
typedef long long LL;
#define int LL
const int inf = 1e9, INF = 0x3f3f3f3f,maxn=2e5+5;
int n,q,a[maxn],sum2[maxn], xo[maxn], sum3[maxn];
map<int, int>hs;
set<int>S[maxn][2];
int cnt = 0;
int read()
{
int x=0;
char c=getchar();
while(c<'0' || c>'9') c=getchar();
while(c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^'0'),c=getchar();
return x;
}
signed main(){
n=read(),q=read();
for(int i=1;i<=n;i++){
a[i]=read();
xo[i] = xo[i-1] ^ a[i];
sum3[i] = sum3[i-1] + (a[i] == 0);
if(!hs.count(xo[i]))hs[xo[i]] = ++ cnt;
S[hs[xo[i]]][i&1].insert(i);
}
while(q --){
int l=read(),r=read();
if(xo[r] ^ xo[l-1]){
puts("-1");
continue;
}
if((r-l+1)&1){
if(sum3[r] - sum3[l-1] == r-l+1)puts("0");
else if((xo[r] ^ xo[l-1]) == 0)puts("1");
else puts("-1");
}else{
if(sum3[r] - sum3[l-1] == r-l+1)puts("0");
else{
int L = l;
int tmp = hs[xo[l-1]];
auto it = S[tmp][L&1].lower_bound(L);
if(it == S[tmp][L&1].end() || *it > r)puts("-1");
else{
if(a[l] == 0 || a[r] == 0)puts("1");
else puts("2");
}
}
}
}
return 0;
}
E
首先把问题抽象成:在一个网格图上,从(0,0) 到 (n,m),每次只能往右/上走,得到一条路径,在路径上选一些点集,问所有点集大小之和
(不等的条件就是不能不走)
注意对于某个点集,可能有多条路径,于是我们只计算一条路径,即先上再右的唯一一条路径
先来考虑“特殊”的点,拐点,注意这个拐点一定是先右再上的
这个是C(n,i) * C(m,i) 的,如果选了i个拐点
这样路径上除了起点终点和拐点,就剩下\(s= n+m+1 - i - 2 = n+m-i-1\)个其它点,看我们需要选哪些(注意拐点确定之后路径就唯一确定了,因为我们已经只计算那唯一一条路径了)
(所以选择拐点的原因就是能够确定路径)
因为要算的是长度之和,因此可以拆开单独算
先算起点终点拐点:长度之和就是\(C(n,i)*C(m,i)*(i+2)*2^{s}\)(i+2是点集大小,也就是序列长度,注意我们是拆开来算了,2^s是可能存在的所有包含着i+2个点的情况,即我在这个路径上选了其它的点,有一个方案数,而这些方案中都包含着i+2,所以序列长度和也都包含)
那么该如何算选了的其它点对答案的贡献?显然贡献就是\(C(n,i)*C(m,i)*[\sum_{j=0}^sC(s,j)*j]\),后面的和式就是选了j个其它点,对答案的贡献
(也可以这么理解:选了i个拐点和j个其它点之后对答案的贡献是i+j+2,只不过我拆开了i+2和j单独算(因为对于i,有很多种j满足条件))
如何处理后面的和式?发现就是\(s*2^{s-1}\),于是做完了,对于每个i把两个式子加起来即可
// by SkyRainWind
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#define mpr make_pair
#define debug() cerr<<"Yoshino\n"
#define rep(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define pii pair<int,int>
using namespace std;
typedef long long LL;
const int inf = 1e9, INF = 0x3f3f3f3f, maxn = 5e6 + 5, mod=1e9+7;
int p2[maxn * 2];
int fac[maxn], inv[maxn];
int pw(int x,int y){
if(y == 0)return 1;
if(y == 1)return x;
int mid = pw(x, y>>1);
if(y&1)return 1ll*mid*mid%mod*x%mod;
return 1ll*mid*mid%mod;
}
int C(int x,int y){
return 1ll*fac[x] * inv[y] % mod * inv[x-y] % mod;
}
void solve(){
int n,m;scanf("%d%d",&n,&m);
if(n > m)swap(n,m);
int ans = 0;
for(int i=0;i<=n;i++){
int cur = 1ll * C(n,i) * C(m,i) % mod;
int s = n+m-i-1;
cur = 1ll * cur * ((1ll * p2[s] * (i+2) % mod + 1ll * s * p2[s-1] % mod) % mod) % mod;
(ans += cur) %= mod;
}
printf("%d\n",ans);
}
signed main(){
p2[0] = 1;
fac[0] = inv[0] = 1;
for(int i=1;i<=maxn - 5;i++)fac[i] = 1ll*fac[i-1]*i%mod;
for(int i=1;i<=10000000;i++) p2[i] = 2ll*p2[i-1]%mod;
inv[maxn - 5] = pw(fac[maxn-5] ,mod-2);
for(int i=maxn-6;i>=1;i--)inv[i] = 1ll*inv[i+1]*(i+1)%mod;
int te;scanf("%d",&te);
while(te --)solve();
return 0;
}
标签:CF1747,int,题解,long,maxn,BAN,include,define
From: https://www.cnblogs.com/SkyRainWind/p/16873755.html