[USACO19FEB]Moorio Kart
我们的神仙教练在考试里放了这道题,当时我非常惊讶啊
背包是\(O(n^3)\)的吧明明是带根号的好吧,那既然要优化的话
NTT!什么时候我们教练会在考试里放多项式了
模数\(1e9+7\)?
任意模数不存在的,我们开int128找一个大一点的\(NTT\)模数就可以了
还是说一下\(NTT\)的做法吧,发现我们要求长度大于\(Y\)的路径可能不太好求,于是我们正难则反一下,我们求出有多少种拼法可以使得路径长度小于\(Y\)就可以了
每一棵树里只能出一条路径,于是我们可以把一棵树的路径信息搞成一个多项式,系数代表这种长度的路径出现了多少次
我们把每棵树的多项式卷起来就是最后的答案了
并不保证随时能通过而且我们不怎么能看懂的代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define re register
#define _LL __int128
#define LL long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#pragma GCC optimize(3)
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("Ofast,no-stack-protector")
char BB[1<<18],*S=BB,*T=BB;
const int maxn=1505;
inline int read() {
char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
}
struct E{int v,nxt,w;}e[maxn<<1];
const LL mod=4222124650659841;
const LL P=1e9+7;
_LL G[2],t,og;
_LL mi[2][16];
int head[maxn],sum[maxn];
int n,m,X,Y,tot,num;
int rev[10000],len,fa[maxn],vis[maxn],pre[maxn];
int tax[1501][2501];LL tp[maxn];
_LL A[9000],B[9000];
LL tmp=1,k=0;
inline void add(int x,int y,int w) {
e[++num].v=y;e[num].nxt=head[x];
head[x]=num;e[num].w=w;
}
inline _LL ksm(_LL a,LL b) {
_LL S=1;
while(b) {if(b&1ll) S=S*a%mod;b>>=1ll;a=a*a%mod;}
return S;
}
void exgcd(LL a,LL b,LL &x,LL &y) {
if(!b) {x=1,y=0;return;}
exgcd(b,a%b,y,x);
y-=a/b*x;
}
inline LL getInv(LL a) {
LL x,y;exgcd(a,P,x,y);
return (x%P+P)%P;
}
void write(LL x){
if(x==0){putchar(48);return;}
int len=0,dg[25];
while(x>0){dg[++len]=x%10ll;x/=10ll;}
for(int i=len;i>=1;i--)putchar(dg[i]+48);
}
inline void NTT(_LL *f,int o) {
for(re int i=0;i<len;i++) if(i<rev[i]) std::swap(f[i],f[rev[i]]);
for(re int i=2,k=0;i<=len;i<<=1,k++) {
int ln=i>>1;
LL og1;
if(!mi[o][k]) {mi[o][k]=og1=ksm(G[o],(mod-1)/i);}
else og1=mi[o][k];
for(re int l=0;l<len;l+=i) {
og=1;
for(re int x=l;x<ln+l;++x) {
t=(f[ln+x]*og)%mod;
f[ln+x]=(f[x]-t+mod)%mod;
f[x]=(f[x]+t)%mod;
og=(og*og1)%mod;
}
}
}
if(!o) return;
_LL inv=ksm(len,mod-2);
for(re int i=0;i<len;i++) f[i]=(f[i]*inv)%mod;
}
void dfs(int x,int Fa) {
++k;
fa[x]=Fa;vis[x]=1;
for(re int i=head[x];i;i=e[i].nxt) {
if(vis[e[i].v]) continue;
dfs(e[i].v,Fa);
}
}
void Dfs(int x,int fa,int p) {
for(re int i=head[x];i;i=e[i].nxt) {
if(e[i].v==fa) continue;
pre[e[i].v]=pre[x]+e[i].w;
if(pre[e[i].v]<Y) tax[p][pre[e[i].v]]++;
else tp[p]+=pre[e[i].v];
Dfs(e[i].v,x,p);
}
}
inline void mul() {
NTT(A,0),NTT(B,0);
for(re int i=0;i<len;i++) A[i]=(A[i]*B[i])%mod;
NTT(A,1);
for(re int i=0;i<Y;i++) A[i]%=P;
//中间取模的简易版任意模数NTT
for(re int i=Y;i<len;i++) A[i]=0;
}
int main() {
G[0]=19ll,G[1]=ksm(19ll,mod-2);
n=read(),m=read(),X=read(),Y=read();
for(re int x,y,z,i=1;i<=m;i++)
x=read(),y=read(),z=read(),add(x,y,z),add(y,x,z);
LL cnt=0,H=0,T=0;
for(re int i=1;i<=n;i++)
if(!vis[i]) {
k=0;++tot,dfs(i,tot);
k=k*(k-1ll)/2ll;sum[tot]=k;
tmp=(tmp*k)%P;
}
Y-=tot*X;
for(re int i=1;i<=n;i++) pre[i]=0,Dfs(i,0,fa[i]);
A[0]=1;len=1;while(len<Y+Y) len<<=1;
for(re int i=0;i<len;i++) rev[i]=rev[i>>1]>>1|((i&1)?len>>1:0);
for(re int i=1;i<=tot;i++) {
for(re int j=0;j<len;j++) B[j]=0;
LL inv=tmp*getInv(sum[i])%P;
for(re int j=0;j<Y;j++) {
B[j]=(tax[i][j]/2);
H+=(inv*(LL)j%P*(LL)(tax[i][j]/2ll)%P);
H%=P;
}
H+=inv*(tp[i]/2ll)%P;H%=P;
mul();
}
//H是所有环的长度和,tmp是所有环的方案数
//cnt是不满足条件的环的方案数,T是不满足条件的环的长度和
for(re int i=1;i<Y;i++)
cnt=(cnt+A[i])%P,T=(T+A[i]*(LL)i%P)%P;
H=(H-T+P)%P;
tmp=(tmp-cnt+P)%P;
H+=tmp*(LL)tot%P*(LL)X%P;H%=P;
if(tot==1) {write(H);return 0;}
if(tot==2) write(H*2ll%P);
else {
LL pw=2,now=4;tot-=2;
for(re int i=1;i<=tot;i++)
pw=(pw*now)%P,now=(now+2ll)%P;
write(H*pw%P);
}
return 0;
}
[USACO19FEB]Moorio Kart的更多相关文章
- [USACO19FEB]Moorio Kart(DP)
Luogu5243 题解 即O(N^2)暴力统计出每个森林的路径,从ctgn个集合中各选出一个数,使得长度>=Y的方案数. 用背包统计.具体实现: \(dp[i+j][0]\leftarrow ...
- DP小小结
入门题 : [Luogu1441]砝码称重 , [NOIP2015]子串 [AHOI2009]中国象棋 , 详见代码 [HNOI2007]梦幻岛宝珠 , 详见代码 [NOIP2012]开车旅行 , 没 ...
- 解题报告:luogu P5543 [USACO19FEB]The Great Revegetation S
题目链接:P5543 [USACO19FEB]The Great Revegetation S 好坑啊,都身败名裂了. 思路一: 考虑染色法,跑一遍搜所就好了,不给代码了. 思路二: 考虑并查集,我想 ...
- [USACO19FEB]Mowing Mischief
题目大意: 给定平面上的一些点,求这些点的一个\(LIS\),并且还需要满足下列式子最小: \[ \sum_{i=1}^{n-1}(a[i+1].x-a[i].x)*(a[i+1].y-a[i].y) ...
- P5242 [USACO19FEB]Cow Dating
题目链接 题意分析 首先我们可以得出计算公式 \[s_i=\prod_{k=1}^i(1-p_k)\] \[f_i=\sum_{k=1}^i\frac{p_k}{1-p_k}\] 那么 \[ans(i ...
- [USACO19FEB]Cow Dating
Luogu5242 通过观察数据,我们可以发现,右端点的取值是单调递增的.于是,我们可以极限一波,用一个双指针法,类似于队列. 右端点的取值满足以下公式: (1-p1)(1-p2)..(1-pn) * ...
- P5541 [USACO19FEB]Sleepy Cow Herding
ri,被黄题虐. 思路:贪心?? 提交:2次 错因:没有特判 题解: 先排序. 最小代价:固定区间长度为\(n\),我们扫一遍数组看区间最多包含几个数,设为 \(mx\) ,答案就是\(n-mx+1\ ...
- [USACO19FEB]Cow Dating——找规律
原题戳这里 题解 显然原题等价于让我们求这个式子\(\prod\limits_{i=l}^{r}(1-p_i)\sum\limits_{i=l}^{r}\frac{p_i}{1-p_i}\)的最大值是 ...
- [USACO19FEB]Painting the Barn G
题意 \(n\)个矩阵\((0\le x_1,y_1,x_2,y_2\le 200)\),可交,可以再放最多两个矩阵(这两个矩阵彼此不交),使得恰好被覆盖\(k\)次的位置最大.\(n,k\le 10 ...
随机推荐
- Resharper 使用帮助-自动生成文件头
VS2012 安装完resharper 后,在resharper选项中选择 Code Editing – File Header Text . 输入自定义的文件头格式.如果需要在文件头外层添加regi ...
- 写一个有字符界面的ssh链接工具
大概的样子 这是大致的样子- 写之前想说的 因为个人工作的的电脑是deepin系统的,系统本身的命令行非常好用,用第三方的ssh工具用不习惯,就想自己写一个. shell脚本是第一次写,写的不是很好, ...
- SpringMVC 面试题
SpringMVC 面试题 什么是Spring MVC ?简单介绍下你对springMVC的理解? Spring MVC是一个基于MVC架构的用来简化web应用程序开发的应用开发框架,它是Spring ...
- java绘图drawString位置的确定
根据api,很容易知道使用方式如下: 指定字符串和坐标即可. 但是简单认为字符串的起始位置就是左上顶点就错了,这样画起来每次的位置都不对,字体的大小不同,位置偏差很大.仔细看api注释后发现,y坐标是 ...
- maven(视频学习)
一.maven的介绍 二.maven的环境搭建 三.maven的结构 四.maven常用的构建命令 五.maven自动创建目录骨架 六.maven中的坐标和仓库 七.在eclipse中安装maven插 ...
- package.json中devDependencies与dependencies的区别
前言:之前一直不懂既然都是项目的依赖,为什么要分成两个部分,devDependencies和dependencies,有什么区别? 安装方式 我们在通过npm安装插件或库时,有三种方式: npm in ...
- [转]vue数据绑定(数据,样式,事件)
1.mounted 与 methods 与 computed 与 watched区别 From:https://blog.csdn.net/qinlulucsdn/article/details/80 ...
- PAT乙级01
1001 害死人不偿命的(3n+1)猜想 (15)(15 分) 卡拉兹(Callatz)猜想: 对任何一个自然数n,如果它是偶数,那么把它砍掉一半:如果它是奇数,那么把(3n+1)砍掉一半.这样一直反 ...
- 带你从零学ReactNative开发跨平台App开发(四)
ReactNative跨平台开发系列教程: 带你从零学ReactNative开发跨平台App开发(一) 带你从零学ReactNative开发跨平台App开发(二) 带你从零学ReactNative开发 ...
- 传递命令行参数示例代码 (C 和 Python)
C语言 在 C 语言中, 使用 main 函数的输入参数 argc 和 argv 传入命令行参数. argc 为 int 类型, 表示传入命令行参数的个数 (argument count); argv ...