uoj279题目交流通道(dp)

题目大意:

神犇星球有 \(n\) 座小城。对于任意两座小城 \(v,u\)\((v≠u)\),吉米多出题斯基想在 \(v,u\) 之间建立一个传送时间为 \(w(v,u)\)的无向传送通道,其中 \(w(v,u)\) 为不超过 \(k\) 的非负整数。建成后,神犇星球的居民可从一座小城出发经过一个或若干个传送通道到达另一座小城交流题目,花费的时间为所有经过的传送通道的传送时间之和。

吉米多出题斯基还没有决定每一个传送通道的传送时间取值,只是对于任意两座小城 \(v,u\),决定了从 \(v\)出发到达 \(u\) 的最短时间要恰好等于 \(d(v,u)\)。但吉米多出题斯基日理万机,于是他找到了你 —— 风璃殇做不出题耶维奇,请你帮助吉米多出题斯基数一数有多少种不同的满足条件的传送通道建设方案吧!

由于方案数可能很大,你只用输出方案数对 \(998244353\) 取模后的结果。

QwQ看到这个题 其实没什么思路

既然没什么思路,我们不妨先特判下不合法的情况

1.存在\(dis[i][k]+dis[k][j]<dis[i][j]\)

2.\(dis[i][j]!=dis[j][i]\)

3.\(dis[i][i]!=0\)

QwQ

看了题解,才知道是一个dp

首先,我们考虑不存在0边的情况,那么对于一条边存在\(dis[i][k]+dis[k][j]==dis[i][j]\),那么\(dis[i][j]\)这个边就可以取\([dis[i][j],k]\)这个范围内的值,那么它的贡献就是\(k-dis+1\)对吧

QwQ然后我们考虑

如果有0边怎么办QwQ

我们可以把所有的0边缩成一个点,先算完每个块每部的贡献,然后再算块外,最后合起来。

QwQ这是一个很值得纪念的一个小套路,我们令\(g[i]\)表示i个点相连的方案数,QwQ因为i个点一共有\(\frac{i(i-1)}{2}\),每个点有\(k+1\)种取值QwQ,所以\(g[i]\)显然等于\((k+1)^{\frac{i(i-1)}{2}}\), QwQ,然后我们令\(f[i]\)表示i个点互相相连,且互相的权值为0的合法方案数

我在计算\(f[i]\)的时候,用的是总方案-不合法的方案\[f[i]=g[i]-\sum_{j=1}^{i-1} C_{i-1}^{j-1} \times f[j] \times g[i-j] \times k^{j(i-j)}\]

QwQ这里的思路是 枚举有几个点相连成0团,然后钦定1个点为合法点,然后乘一乘组合数(一定要乘!!!), 乘上\(f[j]\)(因为0团内的点相连的方案必须是合法的。)再乘上\(g[i-j]\) 另外的点内部的连接是无所谓的。最后乘上\(k^{j(i-j)}\)因为两个团之间的连边不能是0,其余都可以

QwQ那么处理完这个数组呢 0团的内部的方案数也就能迎刃而解了

那么我们应该怎么把它合并起来呢?

对于两个团(点)\(i,j\)

如果存在\(a[i][k]+a[k][j]==a[i][j]\),那么\(ans=ans*qsm(k-a[i][j]+1,size[i]*size[j])\)

如果不存在...是不是没有贡献呢?

并不是这样的

如果不存在的话。我只需要枚举两个团之间至少有一条边是\(a[i][j]\)就行,这里运用了一个小tips

\(ans*(qsm(k-a[i][j]+1,size[i]*size[j])-qsm(k-a[i][j],size[i]*size[j])\)就是所有的情况减去,所有的边都是大于\(a[i][j]\)情况

总之这个题的细节还是很多很多的

直接上代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#define ll long long 

using namespace std;

inline ll read()
{
  ll x=0,f=1;char ch=getchar();
  while (!isdigit(ch)) {if (ch==‘-‘) f=-1;ch=getchar();}
  while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-‘0‘;ch=getchar();}
  return x*f;
}

const ll mod = 998244353;
const int maxn = 510;

int fa[maxn];
ll f[maxn],g[maxn];
int n;
ll k;
ll ans=1;
ll a[maxn][maxn];
ll c[maxn][maxn];
int size[maxn];

int find(int x)
{
    if (fa[x]!=x) fa[x]=find(fa[x]);
    return fa[x];
}

ll qsm(ll i,ll j)
{
    ll ans=1;
    while (j)
    {
        if (j&1) ans=ans*i%mod;
        i=i*i%mod;
        j>>=1;
    }
    return ans;
}

void init(int n)
{
    for (int i=0;i<=n;i++)
      c[i][i]=1,c[i][0]=1;
    for (int i=1;i<=n;i++)
      for (int j=1;j<i;j++)
        c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;
}

int main()
{
  scanf("%d%lld",&n,&k);
  init(n);
  for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) a[i][j]=read();
  bool flag = true;
  for (register int i=1;i<=n;++i)
    for (register int j=1;j<=n;++j)
    {
        if (a[i][i]!=0) flag=false;
        if (a[i][j]!=a[j][i]) flag=false;
        if (a[i][j]>k) flag=false;
    }
  for (register int k=1;k<=n;++k)
    for (register int i=1;i<=n;++i)
      for (register int j=1;j<=n;++j)
        if (a[i][j]>a[i][k]+a[k][j]) flag=false;
  if (!flag) {
      cout<<0;
      return 0;
  }
  f[0]=g[0]=1;
  for (register int i=1;i<=n;i++){
     g[i]=qsm(k+1,i*(i-1)/2);
     f[i]=g[i];
     for (register int j=1;j<=i-1;j++)
     {
        f[i]=(f[i]-c[i-1][j-1]*f[j]%mod*g[i-j]%mod*qsm(k,j*(i-j))%mod+mod)%mod;
     }
  }
  for (int i=1;i<=n;i++) fa[i]=i;
  for (int i=1;i<=n;i++)
  {
    for (int j=1;j<=n;j++)
    {
        if (i==j) continue;
        if (!a[i][j]) fa[find(i)]=fa[find(j)];
      }
  }
  for (int i=1;i<=n;i++) size[find(i)]++;
  for (int i=1;i<=n;i++) if (fa[i]==i) for (int j=i+1;j<=n;j++) if (fa[j]==j)
  {
     bool ok=0;
     for (int p=1;p<=n;p++)
     {
        if (fa[p]!=p) continue;
        if (p==i || p==j) continue;
        if (a[i][p]+a[p][j]==a[i][j]) {
            ok=1;break;
          }
       }
      if (ok) ans=ans*qsm(k-a[i][j]+1,size[i]*size[j])%mod;
      else ans=ans*(qsm(k-a[i][j]+1,size[i]*size[j])-qsm(k-a[i][j],size[i]*size[j])+mod)%mod;
  }
  for (int i=1;i<=n;i++) if (fa[i]==i) ans=ans*f[size[i]]%mod;
  cout<<ans;
  return 0;
}

原文地址:https://www.cnblogs.com/yimmortal/p/10160848.html

时间: 2024-11-07 00:19:58

uoj279题目交流通道(dp)的相关文章

【UTR #2】[UOJ#278]题目排列顺序 [UOJ#279]题目交流通道 [UOJ#280]题目难度提升

[UOJ#278][UTR #2]题目排列顺序 试题描述 "又要出题了." 宇宙出题中心主任 -- 吉米多出题斯基,坐在办公桌前策划即将到来的 UOI. 这场比赛有 n 道题,吉米多出题斯基需要决定这些题目的难度,然后再在汪洋大海中寻找符合该难度的题目. 题目的难度可以用一个 1 到 n 的排列 a1,-,an 表示,其中 ai 表示第 i 道题目在这 n 道题目中是第 ai 简单的题目,即恰有 ai?1 道题目比第 i 道题目简单. 经验丰富的吉米多出题斯基早就悟出了一种科学地决定难

uoj#279. 【UTR #2】题目交流通道(容斥+数数)

传送门 先考虑无解的情况,为以下几种:\(dis_{i,j}+dis_{j,k}<dis_{i,k}\),\(dis_{i,i}\neq 0\),\(dis_{i,j}\neq dis_{j,i}\),\(dis_{i,j}>K\).先大力特判掉 然后来考虑没有边权为\(0\)的时候,把原图中所有的边分类,对于\((i,j)\),如果存在\(k\)使得\(dis_{i,k}+dis_{k,j}=dis_{i,j}\),那么称其为\(B\)类边,否则为\(A\)类边.显然\(A\)类边的权值就是

TOJ4101.Guess Game(TOJ means Tianjin University Online Judge)(dp的思想,但这道题目是假dp)

题意:你要从[1,n]这个n个数中猜出来规定的某个数,现在这个数未知,问你在最糟糕的情况下(但是你采用了最优的策略),你要猜多少次才能猜出这个数.现在有两种条件: 第一种:当你猜的数比指定的那个数小的时候,系统会提示你small; 第二种:当你猜的数比指定的那个数大的时候,系统会提示你wrong,但是从这以后不论你猜的数比指定数大或小,系统将永远提示你wrong. 在这里最糟糕情况可以理解为这个人很倒霉,命运总是让他多猜. 分析: 数列:1,2,3,4,....,k,....,n 比如说你猜了数

Codeforces 23E Tree(树型DP)

题目链接 Tree dp[x][i]表示以x为根的子树中x所属的连通快大小为i的时候 答案最大值 用dp[x][j] * dp[y][k] 来更新dp[x][j + k]. (听高手说这类题的套路其实都差不多) 因为这题输出数据会很大所以用Java-- QAQ 1 import java.util.*; 2 import java.io.*; 3 import java.math.*; 4 5 public class Main{ 6 static final int maxn = 710; 7

hdu 1087 Super Jumping! Jumping! Jumping!(动态规划DP)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1087 Super Jumping! Jumping! Jumping! Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 24452    Accepted Submission(s): 10786 Problem Description No

2017&quot;百度之星&quot;程序设计大赛 - 复赛1003&amp;&amp;HDU 6146 Pok&#233;mon GO【数学,递推,dp】

Pokémon GO Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 171    Accepted Submission(s): 104 Problem Description 众所周知,度度熊最近沉迷于 Pokémon GO. 今天它决定要抓住所有的精灵球! 为了不让度度熊失望,精灵球已经被事先放置在一个2*N的格子上,每一个格子上都

HDU 1069 Monkey and Banana DP LIS变形题

http://acm.hdu.edu.cn/showproblem.php?pid=1069 意思就是给定n种箱子,每种箱子都有无限个,每种箱子都是有三个参数(x, y, z)来确定. 你可以选任意两个参数作为长和宽,第三个是高. 然后要求把箱子搭起来,使得高度最高. 能搭的前提是下面那个箱子的长和宽都 > 上面那个箱子的. 思路: 因为同一个箱子可以产生6中不同的箱子,而每种最多选一个,因为相同的箱子最多只能搭起来一个. 那么可以把所有箱子都弄出来,排序,就是LIS的题目了. dp[i]表示以

Codeforces 474D Flowers (线性dp 找规律)

D. Flowers time limit per test:1.5 seconds memory limit per test:256 megabytes We saw the little game Marmot made for Mole's lunch. Now it's Marmot's dinner time and, as we all know, Marmot eats flowers. At every dinner he eats some red and white flo

NOJ 2033 一页书的书 (组合数+dp)

一页书的书 时间限制(普通/Java) : 1000 MS/ 3000 MS          运行内存限制 : 65536 KByte 总提交 : 55            测试通过 : 12  题目描述 一页书前辈作为一位得道高僧,在他无悔的生涯中创作了许多经典,被世人称作百世经纶.这一天有m个粉丝来膜拜书大,书大很开心,决定送他们每人一本经典.已知一页书一共创作了n部作品,每部作品分别有a1.a2-an份藏本,那么书大一共可以有多少种送书的选择呢?(由于计算结果可能很大,请把结果对100