Codeforces Round #446 Div. 1
B:即使看到n<=22也应该猜到这只是为了写spj。将每个数替换为恰好比他大的数即可,最大值替换为最小值。这样原序列中不包含最小值的集合显然都满足条件,并且容易发现包含最小值的集合的变化量都是最大值-最小值+序列其他两个数的差,这显然是不会为0的。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 23
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
int n,a[N],id[N];
bool cmp(const int&x,const int &y)
{
return a[x]<a[y];
}
signed main()
{
n=read();
for (int i=1;i<=n;i++) a[i]=read(),id[i]=i;
sort(id+1,id+n+1,cmp);
int x=a[id[n]];for (int i=n;i>=2;i--) a[id[i]]=a[id[i-1]];a[id[1]]=x;
for (int i=1;i<=n;i++) cout<<a[i]<<' ';
return 0;
//NOTICE LONG LONG!!!!!
}
C:容易想到随便跑一棵MST然后LCT维护MST,但常数过大。一个众所周知的结论是,所有MST中,所有权值相同的边对连通性的贡献是相同的。于是离线,按边权从小到大考虑,维护将小于当前边权的边加入MST后所得的并查集,对每个询问验证加入该种权值的边后是否会成环即可。当然需要使用带撤销的并查集。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
#define ll long long
#define N 500010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
int n,m,q,p[N],ans[N],cur[N],v[N];
int fa[N],size[N],stk_id[N<<1],stk_fa[N<<1],stk_size[N<<1];
vector<int> id[N],pos[N];
struct data
{
int x,y,z;
bool operator <(const data&a) const
{
return z<a.z;
}
}edge[N],e[N];
int find(int x){return fa[x]==x?x:find(fa[x]);}
bool cmp(const int&x,const int&y)
{
return edge[x].z<edge[y].z;
}
signed main()
{
#ifndef ONLINE_JUDGE
freopen("b.in","r",stdin);
freopen("b.out","w",stdout);
#endif
n=read(),m=read();
for (int i=1;i<=m;i++) edge[i].x=read(),edge[i].y=read(),v[i]=edge[i].z=read();
sort(v+1,v+m+1);
int t=unique(v+1,v+m+1)-v-1;
q=read();
for (int i=1;i<=q;i++)
{
int m=read();ans[i]=1;
while (m--) id[i].push_back(read());
sort(id[i].begin(),id[i].end(),cmp);
for (int j=0;j<id[i].size();j++)
{
int x=lower_bound(v+1,v+t+1,edge[id[i][j]].z)-v;
if (!j||edge[id[i][j]].z!=edge[id[i][j-1]].z) pos[x].push_back(i);
}
}
for (int i=1;i<=m;i++) e[i]=edge[i];
sort(edge+1,edge+m+1);
for (int i=1;i<=n;i++) fa[i]=i,size[i]=1;
int u=0;
for (int i=1;i<=m;i++)
{
int t=i;u++;
while (t<m&&edge[t+1].z==edge[i].z) t++;
for (int j=0;j<pos[u].size();j++)
{
int x=pos[u][j];int top=0;
while (ans[x]&&cur[x]<id[x].size()&&e[id[x][cur[x]]].z==edge[i].z)
{
int p=find(e[id[x][cur[x]]].x),q=find(e[id[x][cur[x]]].y);
if (size[p]<size[q]) swap(p,q);
if (p==q) ans[x]=0;
else
{
top++;stk_id[top]=p;stk_size[top]=size[p];stk_fa[top]=p;
top++;stk_id[top]=q;stk_size[top]=size[q];stk_fa[top]=q;
fa[q]=p;size[p]+=size[q];
}
cur[x]++;
}
while (top) fa[stk_id[top]]=stk_fa[top],size[stk_id[top]]=stk_size[top],top--;
}
for (int j=i;j<=t;j++)
{
int p=find(edge[j].x),q=find(edge[j].y);
if (size[p]<size[q]) swap(p,q);
if (p!=q) fa[q]=p,size[p]+=size[q];
}
i=t;
}
for (int i=1;i<=q;i++) if (ans[i]) puts("YES");else puts("NO");
return 0;
//NOTICE LONG LONG!!!!!
}
E:自闭了把ai-=1看成了ai=1。那就先口胡一下这个东西的做法。
考虑一个大小为j的子集在第i次被选中会提供多少贡献(即该子集的补集恰好全部被重置为1)。显然前i次选择的数应该均在其补集中且恰好覆盖整个补集,第i次之后的数任取。方案数即为S(i,n-j)·(n-j)!·nk-i。
这样我们先对每种大小的子集求其乘积之和。显然有f[i][j]表示前i位选了j个所有方案的乘积之和,转移显然。设f[n][i]=F[i]。
则最后要求的答案就是ΣΣS(i,n-j)·(n-j)!·nk-i·F[j] (i=1~k j=0~n-1)。斯特林数套路地容斥一发,得ΣΣΣC(n-j,x)·xi·(-1)n-j-x·nk-i·F[j] (i=1~k j=0~n-1 x=1~n-j)。可以发现对于巨大的k,最后只剩下对x∈[1,n]每个x求出Σxi·nk-i。显然这是一个公比为x/n的等比数列,直接算就完了。然后O(n2)暴力算式子即可。并且容易发现这个东西是卷积形式,之前的dp也可以分治NTT。当然NTT什么就懒得写了。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define P 1000000007
#define N 5010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
int n,k,a[N],f[N][N],F[N],G[N],C[N][N],ans;
int ksm(int a,int k)
{
int s=1;
for (;k;k>>=1,a=1ll*a*a%P) if (k&1) s=1ll*s*a%P;
return s;
}
int inv(int a){return ksm(a,P-2);}
int calc(int first,int q,int n){if (q==1) return 1ll*first*n%P;return 1ll*first*(P+1-ksm(q,n))%P*inv(P+1-q)%P;}
signed main()
{
#ifndef ONLINE_JUDGE
freopen("b.in","r",stdin);
freopen("b.out","w",stdout);
#endif
n=read(),k=read();
for (int i=1;i<=n;i++) a[i]=read();
f[0][0]=C[0][0]=1;
for (int i=1;i<=n;i++)
{
f[i][0]=C[i][0]=1;
for (int j=1;j<=i;j++)
{
f[i][j]=(f[i-1][j]+1ll*f[i-1][j-1]*a[i])%P;
C[i][j]=(C[i-1][j]+C[i-1][j-1])%P;
}
}
for (int i=0;i<=n;i++) F[i]=f[n][i];
for (int i=1;i<=n;i++) G[i]=calc(1ll*i*ksm(n,k-1)%P,1ll*i*inv(n)%P,k);
for (int j=0;j<n;j++)
for (int x=1;x<=n-j;x++)
if (n-j-x&1) ans=(ans+P-1ll*C[n-j][x]*F[j]%P*G[x])%P;
else ans=(ans+1ll*C[n-j][x]*F[j]%P*G[x])%P;
ans=1ll*ans*inv(ksm(n,k))%P;
cout<<ans;
return 0;
//NOTICE LONG LONG!!!!!
}
回到原题意。注意到(我注意不到)每次res的增加量就是序列所有数乘积的减小量,于是最后要求的就是原序列乘积-修改后序列乘积的期望。当然对于期望统计所有方案最后除以方案数即可。
显然如果第i个数减小了bi,方案数即为k!/∏bi!。此时所有数的乘积是∏(ai-bi)。最终要求Σbi=k时的∏(ai-bi)·k!/∏bi!。
容易想到构造指数型生成函数,∏Σ(ai-j)xj/j!,k次项系数即为答案。
上面这个式子等价于∏aiex-xex,拆开并泰勒公式还原显然可得。于是也就等于enx∏(ai-x)。
这样我们分别算两部分即可。后一部分显然可以分治NTT,但模数不滋磁于是直接O(n2)暴力dp就好了。前一部分暴力展开,k次项系数为nk。答案就很显然了。注意是指数型生成函数,手动乘出第k项时还得乘一下。同样最后计算答案时也可以NTT,为啥要出到5000放个非NTT模数呢。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 5010
#define P 1000000007
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
int n,k,a[N],f[N][N],ans;
int ksm(int a,int k)
{
int s=1;
for (;k;k>>=1,a=1ll*a*a%P) if (k&1) s=1ll*s*a%P;
return s;
}
int inv(int a){return ksm(a,P-2);}
void inc(int &x,int y){x+=y;if (x>=P) x-=P;}
signed main()
{
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
n=read(),k=read();
for (int i=1;i<=n;i++) a[i]=read();
f[0][0]=1;
for (int i=1;i<=n;i++)
{
f[i][0]=1ll*f[i-1][0]*a[i]%P;
for (int j=1;j<=i;j++)
f[i][j]=(1ll*f[i-1][j]*a[i]-f[i-1][j-1]+P)%P;
}
int s=1;
for (int i=0;i<=min(k,n);i++)
{
inc(ans,1ll*ksm(n,k-i)*f[n][i]%P*s%P);
s=1ll*s*(k-i)%P;
}
ans=1ll*ans*inv(ksm(n,k))%P;
ans=(f[n][0]-ans+P)%P;
cout<<ans;
return 0;
}
Codeforces Round #446 Div. 1的更多相关文章
- Codeforces Round #446 (Div. 2)
Codeforces Round #446 (Div. 2) 总体:rating涨了好多,虽然有部分是靠和一些大佬(例如redbag和ShichengXiao)交流的--希望下次能自己做出来2333 ...
- Codeforces Round #446 (Div. 2) C. Pride【】
C. Pride time limit per test 2 seconds memory limit per test 256 megabytes input standard input outp ...
- Codeforces Round #446 (Div. 2) B. Wrath【模拟/贪心】
B. Wrath time limit per test 2 seconds memory limit per test 256 megabytes input standard input outp ...
- Codeforces Round #446 (Div. 2) A. Greed【模拟】
A. Greed time limit per test 2 seconds memory limit per test 256 megabytes input standard input outp ...
- 【Codeforces Round #446 (Div. 2) C】Pride
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 想一下,感觉最后的结果肯定是从某一段开始,这一段的gcd为1,然后向左和向右扩散的. 则枚举那一段在哪个地方. 我们设这一段中所有的 ...
- 【Codeforces Round #446 (Div. 2) B】Wrath
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 倒着来,维护一个最小的点就可以了. [代码] #include <bits/stdc++.h> using namesp ...
- 【Codeforces Round #446 (Div. 2) A】Greed
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 贪心选容量大的瓶子就好 [代码] #include <bits/stdc++.h> #define int long l ...
- Codeforces Round #366 (Div. 2) ABC
Codeforces Round #366 (Div. 2) A I hate that I love that I hate it水题 #I hate that I love that I hate ...
- Codeforces Round #354 (Div. 2) ABCD
Codeforces Round #354 (Div. 2) Problems # Name A Nicholas and Permutation standard input/out ...
随机推荐
- Vue.js 系列教程 1:渲染,指令,事件
原文:intro-to-vue-1-rendering-directives-events 译者:nzbin 如果要我用一句话描述使用 Vue 的经历,我可能会说“它如此合乎常理”或者“它提供给我需要 ...
- Java消息中间件入门笔记 - ActiveMQ篇
入门 消息中间件带来的好处: 1)解耦:系统解耦 2)异步:异步执行 3)横向扩展 4)安全可靠 5)顺序保证 栗子: 通过服务调用让其它系统感知事件发生 系统之间高耦合 程序执行效率低 通过消息中间 ...
- Spring MVC数据绑定入门总结
1.基本类型 基本类型参数不可为空 正例:http://localhost:8080/demo/he?id=2 反例:http://localhost:8080/demo/he?id=(报400错误) ...
- Item 19: 使用srd::shared_ptr来管理共享所有权的资源
本文翻译自modern effective C++,由于水平有限,故无法保证翻译完全正确,欢迎指出错误.谢谢! 博客已经迁移到这里啦 使用带垃圾回收机制语言的程序员指出并嘲笑C++程序员需要遭受防止资 ...
- 朱晔和你聊Spring系列S1E4:灵活但不算好用的Spring MVC
阅读PDF版本 本文会以一些例子来展现Spring MVC的常见功能和一些扩展点,然后我们来讨论一下Spring MVC好用不好用. 使用SpringBoot快速开始 基于之前的parent模块,我们 ...
- centos7下zabbix安装与部署
1.Zabbix介绍 zabbix是一个基于WEB界面的提供分布式系统监视以及网络监视功能的企业级的开源解决方案. zabbix能监视各种网络参数,保证服务器系统的安全运营:并提供灵活的通知机制以让系 ...
- 423. Reconstruct Original Digits from English(Medium)
Given a non-empty string containing an out-of-order English representation of digits 0-9, output the ...
- 新浪2017校园招聘---C++后台研发
一共10道题目,难度不大,就是题量大,时间短. 1. 编程 写一个函数,求出一字符串的所有排列. 2. 编程 实现一个在32位系统下把字符串转换成浮点数的函数 floa ...
- MyEclipse和eclipse的区别
对于新手来说,MyEclipse和eclipse来说的区别可能就是MyEclipse比eclipse多了my,MyEclipse主要为JavaEE开发,而Eclipse主要为Java开发..那么MyE ...
- python的UnboundLocalError: local variable 'xxx' referenced b
一.意思: 本地变量xxx引用前没定义. 二.错误原因 在于python没有变量的声明 , 所以它通过一个简单的规则找出变量的范围 :如果有一个函数内部的变量赋值 ,该变量被认为是本地的,所以 ...