难度:☆☆☆☆☆☆☆☆

/*
对于第一问: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. 14mysql事务、数据库连接池、Tomcat

    14mysql事务.数据库连接池.Tomcat-2018/07/26 1.mysql事务 事务指逻辑上的一组操作,组成这组操作的各个单元,要么全部成功,要么全部不成功. MySQL手动控制事务 开启事 ...

  2. 洛谷—— P1450 [HAOI2008]硬币购物

    P1450 [HAOI2008]硬币购物 硬币购物一共有$4$种硬币.面值分别为$c1,c2,c3,c4$.某人去商店买东西,去了$tot$次.每次带$di$枚$ci$硬币,买$si$的价值的东西.请 ...

  3. Python&机器学习总结(一)

    ① numpy中np.c_和np.r_ np.r_是按列连接两个矩阵,就是把两矩阵上下相加,要求列数相等,类似于pandas中的concat(). np.c_是按行连接两个矩阵,就是把两矩阵左右相加, ...

  4. str类型内置方法

    目录 str类型内置方法 用途 定义方式 常用操作和内置方法 优先掌握 需要掌握 了解 存一个值or多个值 有序or无序 可变or不可变 强化训练 str类型内置方法 用途 字符串数字.字母.下划线组 ...

  5. 1.ARM嵌入式体系结构与接口技术(Cortex-A8版)

    第1章 嵌入式系统基础知识 ---->1.1嵌入式系统的概述 -------->1.1.1嵌入式系统简介 -------->1.1.2嵌入式系统的特点 -------->1.1 ...

  6. [bzoj1004][HNOI2008][Cards] (置换群+Burnside引理+动态规划)

    Description 小春现在很清闲,面对书桌上的N张牌,他决定给每张染色,目前小春只有3种颜色:红色,蓝色,绿色.他询问Sun有多少种染色方案,Sun很快就给出了答案.进一步,小春要求染出Sr张红 ...

  7. 【Codeforces 382C】Arithmetic Progression

    [链接] 我是链接,点我呀:) [题意] 让你在n个数字中再加入一个数字 使得这n+1个数字排序之后 相邻两个数字的差都相同 [题解] 注意相邻为0的情况 这种情况 只有全都相同才行 只有一种情况 然 ...

  8. mongodb shell之使用js(二)

    mongodb shell之使用js(二) mongodb shell不仅是个交互式shell,还能够使用js脚本进行访问. 使用js脚本进行交互的优点与缺点 (1)无需任何驱动或语言支持: (2)方 ...

  9. 【Tomcat】Tomcat替换猫的图片

    参考:网页title上添加图片 直接替换Tomcat安装目录下ROOT下面的favicon.ico图标(名字与前面一样favicon.ico)

  10. codeforces gym 100357 J (网络流)

    题目大意 有n种物品,m种建筑,p个人. n,m,p∈[1,20] 每种建筑需要若干个若干种物品来建造.每个人打算建造一种建筑,拥有一些物品. 主角需要通过交易来建造自己的建筑,交易的前提是对方用多余 ...