bzoj 4386: [POI2015]Wycieczki

这题什么素质,爆long long就算了,连int128都爆……最后还是用long double卡过的……而且可能是我本身自带大常数吧,T了好长时间……

先说一下超级汇点的计数吧,先说结论:

1.将所有点(此题中只有一级点)向一个超级汇点0连边,将矩阵乘n次,相应的f[i][j]即为从i到j的走n步方案数,f[i][0]为i到0走n步的方案数,若在给他乘一个ans矩阵(ans在前),则f[0][0]-n(点数)为所有长度等于n(指数)的路径的方案数。ans矩阵为0向所有其他点连边。

2.若在1中,将0想自己连边,则每次相乘都会积累,最终得出的即为所有长度小于等于n的路径方案数。

具体可以这样理解:

ans矩阵相当于从超级汇点出发走一步,每乘一个base矩阵,相当于走一步,乘了n次后,相当于走n步,但是还要再乘一个base,相当于各点回到0,而计数器中仍保留着从0走出的方案数,此时f[0][0]-点数即为答案。(这种问题自己手模一下会更容易理解吧)。

然后是题解:

边权只有1,2,3三种,考虑拆点(在‘迷路’中也用到了同样的方法),将一个点分为三级,$get(int po,int w){return (po-1)*3+w;}$,将每个点的第一级向第二级连边,第二级向第三级连边,对于一条a->b,长度为w的边,从a的第w级向b的第一级连长度为1的边。

代码实现:

  1. for(int i=;i<=m;i++)
  2. {
  3. a=read(),b=read(),c=read();
  4. cs.m[get(a,c)][get(b,)]++;
  5. }
  6. for(int i=;i<=n;i++)
  7. {
  8. cs.m[get(i,)][get(i,)]++;
  9. cs.m[get(i,)][get(i,)]++;
  10. }

这样就得到了一个初始矩阵,构造出ans矩阵,显然可以二分枚举长度解决,但是复杂度比较高会T,考虑倍增,提前预处理出初始矩阵乘$2^i$后的矩阵,像LCA那样搞就可以了。

然而这道题还有几个坑点:

方案数乘的时候会爆longlong(如果你打的恶心点连__int128都会爆),可以加判断,个人感觉比较麻烦,于是就用了double,还会爆?丝毫不慌还有long double。

然后就T了,用lemon测了一下,跑了一百多秒,好在都跑对了,其实这不是long double的锅,和我自带的大常数关系也不大,在预处理倍增数组时我固定给他求到了65,导致时间比较长,其实可以记录一下:

  1. for(int i=;i<=;i++,imax++){F[i]=F[i-]*F[i-];if((ans*F[i]).count()>k)break;}

然后就A了,跑得还挺快。其实我还是搞不懂为啥会差这么多,固定求到65复杂度也是$n^3log_n$啊……

  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdio>
  4. #include<cmath>
  5. #define N n*3
  6. #define LD long double
  7. #define LL long long
  8. using namespace std;
  9. int n,m;LL k;
  10. struct jz
  11. {
  12. LD m[121][121];
  13. LD count() {return m[0][0]-n;}
  14. }cs,ans,F[70];
  15. jz operator * (jz &a,jz &b)
  16. {
  17. jz ans;
  18. for(int i=0;i<=N;i++)
  19. for(int j=0;j<=N;j++)
  20. ans.m[i][j]=0;
  21. for(int i=0;i<=N;i++)
  22. for(int j=0;j<=N;j++)
  23. for(int k=0;k<=N;k++)
  24. ans.m[i][j]+=a.m[i][k]*b.m[k][j];
  25. return ans;
  26. }
  27. inline int get(const register int po,const register int w){return (po-1)*3+w;}
  28. inline LL read()
  29. {
  30. LL s=0;char a=getchar();
  31. while(a<'0'||a>'9')a=getchar();
  32. while(a>='0'&&a<='9'){s=s*10+a-'0';a=getchar();}
  33. return s;
  34. }
  35. signed main()
  36. {
  37. // freopen("10.in","r",stdin);
  38.  
  39. n=read(),m=read(),k=read();
  40. int a,b,c;
  41. for(int i=1;i<=m;i++)
  42. {
  43. a=read(),b=read(),c=read();
  44. cs.m[get(a,c)][get(b,1)]++;
  45. }
  46. for(int i=1;i<=n;i++)
  47. {
  48. cs.m[get(i,1)][get(i,2)]++;
  49. cs.m[get(i,2)][get(i,3)]++;
  50. }
  51. LL imax=1;
  52. cs.m[0][0]=1;
  53. for(int i=1;i<=n;i++)cs.m[get(i,1)][0]++;
  54. for(int i=1;i<=n;i++)ans.m[0][get(i,1)]=1;
  55. F[0]=cs;
  56. for(int i=1;i<=65;i++,imax++){F[i]=F[i-1]*F[i-1];if((ans*F[i]).count()>k)break;}
  57. if((ans*F[imax]).count()<k){cout<<-1<<endl;return 0;}
  58. LL num=0;
  59. for(int i=imax;i>=0;i--)
  60. {
  61. jz tm=ans*F[i];
  62. if(tm.count()<k){num+=1ll<<i;ans=ans*F[i];}
  63. }
  64. cout<<num<<endl;
  65. }

bzoj 4386: [POI2015]Wycieczki的更多相关文章

  1. BZOJ 4386 Luogu P3597 [POI2015]Wycieczki (矩阵乘法)

    题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=4386 (luogu) https://www.luogu.org/pro ...

  2. BZOJ 4385: [POI2015]Wilcze doły

    4385: [POI2015]Wilcze doły Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 648  Solved: 263[Submit][ ...

  3. BZOJ 4384: [POI2015]Trzy wieże

    4384: [POI2015]Trzy wieże Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 217  Solved: 61[Submit][St ...

  4. Bzoj 3747: [POI2015]Kinoman 线段树

    3747: [POI2015]Kinoman Time Limit: 60 Sec  Memory Limit: 128 MBSubmit: 553  Solved: 222[Submit][Stat ...

  5. BZOJ 3747 POI2015 Kinoman 段树

    标题效果:有m点,每个点都有一个权值.现在我们有这个m为点的长度n该序列,寻求区间,它仅出现一次在正确的点区间内值和最大 想了很久,甚至神标题,奔说是水的问题--我醉了 枚举左点 对于每个请求留点右键 ...

  6. BZOJ 4380 [POI2015]Myjnie | DP

    链接 BZOJ 4380 题面 有n家洗车店从左往右排成一排,每家店都有一个正整数价格p[i]. 有m个人要来消费,第i个人会驶过第a[i]个开始一直到第b[i]个洗车店,且会选择这些店中最便宜的一个 ...

  7. BZOJ4386 [POI2015]Wycieczki 矩阵+倍增

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4386 题解 一眼就可以看出来是邻接矩阵快速幂. 可是这里的边权不为 \(1\).不过可以发现, ...

  8. BZOJ4386 : [POI2015]Wycieczki

    将每个点拆成三个点,并将转移转化为矩阵乘法,然后倍增即可求出第$k$短路的长度,注意对爆long long情况的处理. 时间复杂度$O(n^3\log k)$. #include<cstdio& ...

  9. BZOJ 3747 POI2015 Kinoman

    因为上午没有准备够题目,结果发现写完这道题没题可写了QAQ 又因为这道题范围是100w,我写了发线段树,以为要T,上午就花了一个小时拼命卡常数 结果下午一交居然过了QAQ 我们考虑枚举L,求最大R使得 ...

随机推荐

  1. jeecms系统使用介绍——jeecms中的内容、栏目、模型之间的关系

    转载:https://blog.csdn.net/dongdong9223/article/details/76578120 jeecms是一款很不错的cms产品,之前在文章<基于Java的门户 ...

  2. 文本流向 layout-flow

    作用与语法 文本流向layout-flow用来定义网页中的文本流向方式. 即排列方式,主要有两个属性,分别是horizonta (水平的) 和vertical-ideographic (垂直的). 文 ...

  3. Leetcode91.Decode Ways解码方法

    一条包含字母 A-Z 的消息通过以下方式进行了编码: 'A' -> 1 'B' -> 2 ... 'Z' -> 26 给定一个只包含数字的非空字符串,请计算解码方法的总数. 示例 1 ...

  4. LinqToExcel 简洁与优美开源库

    转载:https://www.cnblogs.com/codefish/archive/2013/04/08/3009098.html 正在做项目,同事问道有啥简单的方法读取excel到DataTab ...

  5. Django多业务模块的写法

    from django.shortcuts import render # Create your views here. from django.shortcuts import HttpRespo ...

  6. 【JZOJ4711】【NOIP2016提高A组模拟8.17】Binary

    题目描述 输入 输出 样例输入 6 6 8 9 1 13 9 3 1 4 5 2 6 9 1 3 7 2 7 7 1 6 1 2 11 13 样例输出 45 19 21 数据范围 解法 40%暴力即可 ...

  7. 一个不错的插件(软件).NET开发

    http://www.gcpowertools.com.cn/products/default.htm 葡萄城 先记录一下!

  8. springboot自定义错误页面(转)

    方法一:Spring Boot 将所有的错误默认映射到/error, 实现ErrorController @Controller @RequestMapping(value = "error ...

  9. 2018-8-10-C#-不能用于文件名的字符

    title author date CreateTime categories C# 不能用于文件名的字符 lindexi 2018-08-10 19:16:52 +0800 2018-02-22 1 ...

  10. 【水滴石穿】react-native-app

    项目地址:https://github.com/WQone/react-native-app 这个是一个非常优秀的小姐姐写的,希望大家能够以她为榜样,一起加油进步呀- 先看效果 分析package.j ...