难度:☆☆☆☆☆☆☆☆

/*
对于第一问:f[i][j]表示前i个数,当前黑板上的数为j的概率
当前有三种情况
1.当前数不是j的倍数—>黑板上的数字改变。
2.当前数是j的倍数且当前数在前i个数中(已经选过)
3.当前数是j的倍数且没有选过
转移:f[i+1][j]=((j的倍数个数-i)*f[i][j]+f[i][gcd(j,k)]) 的平均值 j的倍数个数-i是没选过的j的倍数。
对于第二问,考虑博弈论中sg函数。可知sg[i][1]二维含义同f数组)必定为0(最后黑板上剩下1必败) sg[n][i]=0(选完了必败) 同样枚举上述三种情况,取后续状态mex值即可。
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define eps 1e-8
#define N 1000
using namespace std;
inline int gcd(int a, int b)
{
return b == ? a : gcd(b, a % b);
}
int sg[N + ][N + ], g[N + ][N + ], f[N + ], n, a[N + ];
double dp[N + ][N + ], ans = ;
bool getsg(int x, int y)
{
if (x == ) return ;
if (sg[x][y] != -) return sg[x][y];
bool flag = ;
if (f[x] > y) flag &= getsg(x, y + );
for (int i = ; i <= n; i++)
if (g[x][i] != x)
flag &= getsg(g[x][i], y + );
sg[x][y] = !flag;
return sg[x][y];
}
int main()
{
freopen("cards.in", "r", stdin);
freopen("cards.out", "w", stdout);
scanf("%d", &n);
int mx = ;
for (int i = ; i <= n; i++)
{
scanf("%d", a + i);
mx = max(mx, a[i]);
g[][i] = a[i];
}
for (int i = ; i <= mx; i++)
for (int j = ; j <= n; j++)
f[i] += (a[j] % i == ), g[i][j] = gcd(i, a[j]);
dp[][] = ;
for (int i = ; i <= n; i++)
for (int j = ; j <= mx; j++)
if (dp[i - ][j] > eps)
{
dp[i][j] += dp[i - ][j] * (f[j] - i + ) / (n - i + );
for (int k = ; k <= n; k++)
if (g[j][k] != j)
{
if (g[j][k] != )
dp[i][g[j][k]] += dp[i - ][j] / (n - i + );
else
ans += (i + & ) * dp[i - ][j] / (n - i + );
}
}
if (n & )
for (int j = ; j <= mx; j++) ans += dp[n][j];
printf("%.9lf ", ans);
memset(sg, -, sizeof(sg));
if (getsg(, )) puts("1.000000000");
else puts("0.000000000");
return ;
}

/*
对于60~80分,可以n^2暴力,断掉每条边时,O(N)求每个部分的直径,然后相乘。 正解:倒序加边,考虑两棵树合并的时候新直径一定是原来两个直径四个断点任意两个的路径。
所以可以首先求LCA倍增处理两点间路径,然后求最大。更新答案要用逆元。
*/
#include<iostream>
#include<cstdio>
#include<cstring> #define N 100007
#define mod 1000000007
#define ll long long using namespace std;
int a[N],dep[N],sum[N],fa[N][],head[N],del[N];
int D[N][],ans[N],f[N],len[N],end[];
int n,m,pre,cnt;
struct edge{
int u,v,net;
}e[N<<]; inline int read()
{
int x=,f=;char c=getchar();
while(c>''||c<''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
} inline void add(int u,int v)
{
e[++cnt].u=u;e[cnt].v=v;e[cnt].net=head[u];head[u]=cnt;
} void dfs(int u,int from)
{
fa[u][]=from;dep[u]=dep[from]+;
sum[u]=sum[from]+a[u];
for(int i=;i<=;i++) fa[u][i]=fa[fa[u][i-]][i-];
for(int i=head[u];i;i=e[i].net)
{
int v=e[i].v;
if(v!=from)dfs(v,u);
}return;
} int find(int x)
{
return x==f[x]?x:f[x]=find(f[x]);
} int ksm(int a,int b)
{
int res=;
while(b)
{
if(b&) res=1ll*res*a%mod;
b>>=;a=1ll*a*a%mod;
}return res%mod;
} int lca(int u,int v)
{
if(dep[u]<dep[v]) swap(u,v);
int t=dep[u]-dep[v];
for(int i=;i<;i++)
if(t&(<<i)) u=fa[u][i];
if(u==v) return u;
for(int i=;i>=;i--)
{
if(fa[u][i]!=fa[v][i])
{
u=fa[u][i];
v=fa[v][i];
}
}return fa[u][];
} int getlen(int u,int v)
{
int L=lca(u,v);
return sum[u]+sum[v]-*sum[L]+a[L];
} int main()
{
freopen("forest.in","r",stdin);
freopen("forest.out","w",stdout);
int x,y;
n=read();pre=;
for(int i=;i<=n;i++)
{
a[i]=read();f[i]=i;
pre=(ll)pre*a[i]%mod;
D[i][]=D[i][]=i;len[i]=a[i];
}
for(int i=;i<n;i++)
{
x=read();y=read();
add(x,y);add(y,x);
}
dfs(,);int t=n;ans[n]=pre;
for(int i=;i<n;i++) del[i]=read(); for(int i=n-;i;i--)
{
int id=del[i],u=e[id*-].u,v=e[id*-].v;
u=find(u);v=find(v);
if(len[u]<len[v]) swap(u,v);
int tmax=len[u];
for(int j=;j<;j++) end[j]=D[u][j];
for(int j=;j<;j++)
for(int k=;k<;k++)
{
int l=getlen(D[u][j],D[v][k]);
if(l>tmax)
{
tmax=l;
end[]=D[u][j];end[]=D[v][k];
}
} pre=(ll) pre*ksm(len[u],mod-)%mod;
pre=(ll) pre*ksm(len[v],mod-)%mod;
f[v]=u;len[u]=tmax;
for(int j=;j<;j++) D[u][j]=end[j];
pre=(ll) pre*len[u]%mod;
ans[--t]=pre;
}
for(int i=;i<=n;i++) printf("%d\n",ans[i]);
return ;
}

/*
这题确实是恶心,并且貌似没有部分分......
让我们来瞻仰一下std做法
考虑两列的情况。若两列颜色分别为A,B,则A独有的颜色就是A—A∩B ,B同理。
若是多列那还是设两边两列为A,B,中间多列为C,那根据题目结论可以知道C一定是A∩B的子集。枚举A中独有颜色个数,B中独有颜色个数与A中相同。若有j独有,i共有C(K,i)*C(k-i+1,j)*C(k-i-j,j)
因为每次选择都必须是恰好那些颜色,不能少,所以用总方案数减去不是恰好的就可以了。
*/
# include<iostream>
# include<cstdio>
# include<cstring>
# include<cstdlib> using namespace std;
const int pp=;
int c[][],f[],p[],ni[];
int n,m,k,nn; inline int power(int x,int n)
{
int ans=,tmp=x;
while (n)
{
if (n&) ans=(long long)ans*tmp%pp;
tmp=(long long)tmp*tmp%pp;n>>=;
}
return ans;
} void Count_c()
{
for (int i=;i<=nn;i++) c[i][]=;
for (int i=;i<=nn;i++)
for (int j=;j<=i;j++)
{
c[i][j]=c[i-][j-]+c[i-][j];
if (c[i][j]>=pp) c[i][j]-=pp;
}
} void Count_p()
{
int mm=(m-)*n;
for (int i=;i<=nn;i++)
p[i]=power(i,mm);
} void Count_f()
{
f[]=;f[]=;
for (int i=;i<=nn;i++)
{
f[i]=power(i,n);
for (int j=;j<i;j++)
{
f[i]-=(long long)f[j]*c[i][j]%pp;
if (f[i]<=-pp) f[i]+=pp;
}
if (f[i]<) f[i]+=pp;
}
} void Count_ni()
{
ni[]=;
for (int i=;i<=nn;i++)
ni[i]=power(i,pp-);
} int main()
{
freopen("photo.in","r",stdin);
freopen("photo.out","w",stdout);
scanf("%d%d%d",&n,&m,&k);
nn=min(n,k);
if (m==)
printf("%d\n",power(k,n));
else
{
Count_c();Count_p();
Count_f();Count_ni();
long long tmp=,tmp1=,sum=,sum1;
for (int s=;s<=nn;s++)
{
tmp=tmp*ni[s]%pp;
tmp=tmp*(k-s+)%pp;
tmp1=;sum1=;
for (int j=;j<=s;j++)
{
sum1+=tmp1*c[s][s-j]%pp*p[s-j]%pp;
if (sum1>=pp) sum1-=pp;
tmp1=tmp1*ni[j+]%pp;
if (k-s<j+) break;
tmp1=tmp1*(k-s-j)%pp;
}
sum+=tmp*f[s]%pp*f[s]%pp*sum1%pp;
if (sum>=pp) sum-=pp;
}
printf("%d\n",sum);
}
fclose(stdin);
fclose(stdout);
return ;
}

湖南集训day6的更多相关文章

  1. 主席树 || 可持久化线段树 || BZOJ 3653: 谈笑风生 || Luogu P3899 [湖南集训]谈笑风生

    题面:P3899 [湖南集训]谈笑风生 题解: 我很喜欢这道题. 因为A是给定的,所以实质是求二元组的个数.我们以A(即给定的P)作为基点寻找答案,那么情况分两类.一种是B为A的父亲,另一种是A为B的 ...

  2. LOJ #6074. 「2017 山东一轮集训 Day6」子序列

    #6074. 「2017 山东一轮集训 Day6」子序列 链接 分析: 首先设f[i][j]为到第i个点,结尾字符是j的方案数,这个j一定是从i往前走,第一个出现的j,因为这个j可以代替掉前面所有j. ...

  3. P3900 [湖南集训]图样图森破

    P3900 [湖南集训]图样图森破 链接 分析: 感觉像个暴力. 可以枚举回文串的回文中心,即枚举一个串,枚举一个串的位置作为回文中心,然后求出这个串内的回文串的长度. 此时如果回文串两端都没有到这个 ...

  4. 2019暑期金华集训 Day6 杂题选讲

    自闭集训 Day6 杂题选讲 CF round 469 E 发现一个数不可能取两次,因为1,1不如1,2. 发现不可能选一个数的正负,因为1,-1不如1,-2. hihoCoder挑战赛29 D 设\ ...

  5. 2019暑期金华集训 Day6 计算几何

    自闭集训 Day6 计算几何 内积 内积不等式: \[ (A,B)^2\le (A,A)(B,B) \] 其中\((A,B)\)表示\(A\cdot B\). (好像是废话?) 叉积 \[ A\tim ...

  6. 考前停课集训 Day6 垒

    Day 6 今天在家里的 家里蹲 其实是day7的时候想到要写day6了 草率补充一下 NOIP考前棕名退不掉咯 你觉得我还会打洛谷的题目吗? 依然退步 没用心 T1 分火腿 数论题 我感觉挺难的 T ...

  7. 2022寒假集训day6

    day6上午还是做四道题T1区域[上机练习]1.编程计算由"*"号围成的下列图形的面积.面积计算方法是统计*号所围成的闭合曲线中水平线和垂直线交点的数目.如下图所示,在 10*10 ...

  8. 省队集训day6 C

    Description 给定平面上的 N 个点, 其中有一些是红的, 其他是蓝的.现在让你找两条平行的直线, 使得在保证    不存在一个蓝色的点 被夹在两条平行线之间,不经过任何一个点, 不管是蓝色 ...

  9. 省队集训day6 B

    一道AC自动机题···· 一定要把一个节点没有的儿子接到它fai的儿子,否则会卡到n^2的······· #include<cstdio> #include<iostream> ...

随机推荐

  1. 小程序接口越过域名和https限制方法

    都知道小程序上线接口需要域名,还需要https,就算是体验版的都是需要的,这样就筛选掉一大批开发者,像我这样只有学生轻量级服务器的学生要开发自己的小程序就很为难,但今天确惊奇的在小程序社区里面找到了用 ...

  2. [Luogu] P3701 「伪模板」主席树

    题目背景 byx和手气君都非常都非常喜欢种树.有一天,他们得到了两颗奇怪的树种,于是各自取了一颗回家种树,并约定几年后比一比谁种出来的树更加牛x. 题目描述 很快,这棵树就开花结果了.byx和手气君惊 ...

  3. ubuntu_linux自动补全出现问题

    问题:输入: cd p,使用Tab补全,期望进入pub_work目录,虽然自动补全,成功进入目录:却给我打印一连串的字符,纠结: fly@Flyme:~$ cd p+ local cur prev w ...

  4. 设置NODE_ENV=test环境变量

    之前开发时因为有内网测试环境和外网测试环境,再部署打包时总是切换两个域名,比较麻烦,所以最好能设置一个环境变量,来控制两个域名,于是做了如下配置: "scripts": { &qu ...

  5. 【Codeforces 493C】Vasya and Basketball

    [链接] 我是链接,点我呀:) [题意] 题意 [题解] 枚举三分线(离散后)的位置 然后根据预处理的前缀和,快速算出两个队伍的分数. [代码] #include <bits/stdc++.h& ...

  6. Codeforces Round #234 (Div. 2)

    A. Inna and Choose Options time limit per test 1 second memory limit per test 256 megabytes input st ...

  7. Navicat使用技巧

    1.有时按快捷键Ctrl+F搜某条数据的时候搜不到,但是能用sql查出来,这是怎么回事? Ctrl+F只能搜本页数据,不在本页的数据搜不到,navicat每页只显示1000条数据.在数据多的时候nav ...

  8. java查询MySQL时,MySQL中tinyint长度为1时转换为boolean

    看到别人代码,MySQL数据库中,有下面这个字段,tinyint(1) 这时候java代码中取出来的数据类型就是boolean类型,如果长度 > 1的话,就会变成int类型,特意查了一下,这里参 ...

  9. spring-boot-starter-actuator(健康监控)配置和使用

    在生产环境中,需要实时或定期监控服务的可用性.Spring Boot的actuator(健康监控)功能提供了很多监控所需的接口,可以对应用系统进行配置查看.相关功能统计等. 集成: <depen ...

  10. Nginx 重写规则指南

    作者:运维生存时间 - 默北 链接:www.ttlsa.com/nginx/nginx-rewriting-rules-guide/ 当运维遇到要重写情况时,往往是要程序员把重写规则写好后,发给你,你 ...