P4128 [SHOI2006]有色图

本文探讨了Polya定理在边置换问题中的应用,通过解析边置换的数学模型,详细介绍了如何利用循环节的概念计算边的循环个数,并提出了一种基于全排列和循环同构的高效算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

传送门

数学渣渣看题解看得想死Ծ‸Ծ

首先发现这玩意儿看着很像polya定理
\[L=\frac{1}{|G|}\sum_{i\in G}m^{w(i)}\]
然而polya定理只能用来求点的置换,边的置换是布星的

于是我们考虑一个点的置换,把它写成若干循环的乘积\((a_1,a_2,..)(b_1,b_2,...)...\)

1.对于不在同一个循环里的点,比方说一条边\((a_1,b_1)\),那么和它在同一个循环的边有\(((a_1,b_1),(a_2,b_2),...)\)\(a\)的循环节为\(l_1\)\(b\)的循环节为\(l_2\),那么这个边的循环的循环节长度就是\(lcm(l_1,l_2)\),而总共的边数为\(l_1*l_2\),那么循环的个数就是\(\frac{l_1*l_2}{lcm(l_1,l_2)}=gcd(l_1,l_2)\)

2.对于在同一个循环内的点,设\(a\)的循环节长度为\(l_1\)

如果\(l_1\)长度为奇数,那么循环的长度就是\(l_1\),总共有\(C_{l_1}^{2}\)条边,那么循环的个数就是\(\frac{l-1}2\)

如果\(l_1\)长度为偶数,除了上面的情况之外,还有一种很gg的情况就是比方说\((a_1,a_{l_1/2+1})\)的边所在的循环,这个循环的长度是\(l_1/2\),占的边数为\(l_1/2\),除此之外其他的情况都是一样的,所以循环的个数就是\(\frac{\frac{l(l-1)}{2}-\frac{l}2}{l}+1=\frac l 2\)

那么,总共的边的置换就是
\[c=\sum_{i=1}^k\lfloor\frac{l_i}{2}\rfloor+\sum_{i=1}^k\sum_{j=i+1}^ngcd(l_i,l_j)\]

然而如果直接枚举的话复杂度是带一个感叹号的……然而我们只需要知道所有的\(l_i\)就行了,而不需要知道循环里具体是什么数字……所以会T就是我们知道的太多了

于是我们可以枚举\(l_i\),为了不重不漏保证\(l_i\)不降,先考虑如果\(l_i\)互不相同的话有多少种方案。我们可以这样理解,枚举\(n\)个数字的全排列,然后按\(l_i\)从左到右依次分组,那么这样肯定就是一个置换了……然后对于其中的每一个循环\((a_1,a_2,...,a_l)\)来说,\((a_2,a_3,...,a_l,a_1)...\)之类的其实是跟它一样的,也就是说每个循环有\(l_i\)个同构的,所以要除掉,那么方案数就是
\[S=\frac{n!}{\prod_{i=1}^k l_i}\]

然而现在问题是\(l_i\)有可能会相等,如果按上面那样考虑的话有可能会有两个\(l_i\)相等的循环被算到不同的里面了……所以还要设\(B_i\)\(l_j==i\)的个数,然后除掉他们中间排列的个数,那么方案数应该是
\[S=\frac{n!}{\prod_{i=1}^k l_i*B_i!}\]

然后dfs暴力找\(l_i\)即可

最后就是
\[Ans=Ans+S*m^c\]

之后就是抄代码了

//minamoto
#include<bits/stdc++.h>
#define int long long
#define fp(i,a,b) for(register int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(register int i=a,I=b-1;i>I;--i)
using namespace std;
const int N=105;
int ans,P,n,m,fac[N],rec[N];
int gcd(int x,int y){return y?gcd(y,x%y):x;}
int ksm(int x,int y){
    int res=1;
    for(;y;y>>=1,x=x*x%P)if(y&1)res=res*x%P;
    return res;
}
void calc(int x){
    int sum=0,mul=1,now=1;
    fp(i,1,x)sum+=rec[i]/2;
    fp(i,1,x)fp(j,i+1,x)sum+=gcd(rec[i],rec[j]);
    fp(i,1,x)(mul*=rec[i])%=P;
    fp(i,2,x){
        if(rec[i]!=rec[i-1])(mul*=fac[now])%=P,now=0;
        ++now;
    }(mul*=fac[now])%=P,mul=fac[n]*ksm(mul,P-2)%P;
    (ans+=mul*ksm(m,sum)%P)%=P;
}
void dfs(int k,int x,int s){
    if(!x)calc(k-1);if(x<s)return;
    fp(i,s,x)rec[k]=i,dfs(k+1,x-i,i);
}
signed main(){
//  freopen("testdata.in","r",stdin);
    scanf("%lld%lld%lld",&n,&m,&P),fac[0]=1;
    fp(i,1,n)fac[i]=fac[i-1]*i%P;
    dfs(1,n,1);(ans*=ksm(fac[n],P-2))%=P;
    printf("%lld\n",ans);return 0;
}

转载于:https://www.cnblogs.com/bztMinamoto/p/10054795.html

使用:网络需要在像和输出概率(评分0-1)之间过滤不适合工作的片。评分<0.2表示像具有较高概率是安全的。评分>0.8表明极有可能是不适合工作(NSFW)像。我们建议开发者根据用例和像类型的不同选择合适的阈值。根据使用情况、定义以及公差的不同会产生误差。理想情况下,开发人员应该创建一个评价集,根据“什么是安全的”对他们的应用程序进行定义,然后适合ROC曲线选择一个合适的阈值。结果可以通过微调你的数据/ uscase /定义NSFW的模型的改进。我们不提供任何结果的准确性保证。使用者适度地结合机器学习解决方案将有助于提高性能。模型描述:我们将不适合工作的片(NSFW)作为数据集中的积极对象,适合工作的片作为消极对象来进行训练。所有这些被训练得片都被打上了特定的标签。所以由于数据本身的原因,我们无法发布数据集或者其他信息。我们用非常不错的名字叫“CaffeOnSpark”的架构给“Hadoop”带来深度学习算法,并且使用Spark集群来进行模型训练的实验。在此非常感谢 CaffeOnSpark 团队。深度模型算法首先在 ImageNet 上生成了1000种数据集,之后我们调整不适合工作(NSFW)的数据集比例。我们使用了50 1by2的残差网络生成网络模型。模型通过 pynetbuilder 工具以及复制残余网络的方法会产生50层网络(每层网络只有一半的过滤器)。你可以从这里获取到更多关于模型产生的信息。更深的网络或者具有更多过滤器的网络通常会更精确。我们使用剩余(residual)网络结构来训练模型,这样可以提供恰到好处的精确度,同样模型在运行以及内存上都能保持轻量级。 标签:opennsfw
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值