博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
我的每日所学
阅读量:5094 次
发布时间:2019-06-13

本文共 3111 字,大约阅读时间需要 10 分钟。

2019.3.2

三元环计数

有2种方法:假设有$m$条边

法1:将每一个点分为2类,第一类点的度数$ <= \sqrt{m}$,第二类度数$ >= \sqrt{m}$

对于第一类点,暴力枚举这个点的2条向外连的边,然后看这两条边指向的点有没有连边

对于第二类点,个数不超过$ >= \sqrt{m}$,所以这几个点立方级连边即可

这种方法要用到哈希表,常数很大

法2:将每一条边定向,从度数小的点连向度数大的点。如果度数相同则从编号小的连向编号大的

然后枚举每个点$i$,枚举$i$的出点$j$,打上值为$i$的标记

对于每个枚举的$j$,暴力枚举出点$k$

,若$k$有$i$的标记,则证明”$i$有一条出边指向$k$",统计答案

这样子是$O(m\sqrt{m})$的,为什么?

分度数$<=\sqrt{m}$ 和$ >= \sqrt{m}$ 讨论

我们发现耗在每一条边时间可以写成:$out[v[1]]+out[v[2]]+....+out[v[m]]$,其中$v[i]$表示第$i$条边的“出点”,$out[i]$表示第i个点的出度

对于$out[v[]]<=\sqrt{m}$的边,我们发现每一个$out[v[]]$卡到最大是$\sqrt{m}$,$m$个数的时间复杂度不会超过$O(m\sqrt{m})$

对于$out[v[]]>\sqrt{m}$的边,似乎不是很好分析

我们发现度数$>\sqrt{m}$的点至多只有$\sqrt{m}$个,而这些点只可能向度数更大的点连边,所以出度不超过$\sqrt{m}$

而且度数$<=\sqrt{m}$的点本来出度就不超过$\sqrt{m}$

所以每一个点的出度不超过$\sqrt{m}$

这样就对了

代码:

while(m--){        int x,y;        scanf("%d%d",&x,&y);        e1[++ct]=x;        e2[ct]=y;        ot[x]++;        in[y]++;    }    for(int i=1;i<=ct;i++){        int p=(in[e1[i]]

例题:jzoj5803. 【2018.8.12省选模拟】girls 

其实这题不是完全意义上的三元环计数

前面还要求出含0条,1条,2条边的答案

然后再对现在的含3条边的答案进行容斥,才是最终结果

6.26

杨表求lis期望值

等会填坑

7.1 

excrt

这个算法我去年就学过,但是因为自己弱,一直没时间实现

考虑把2个方程组$x%a=b$ $x%c=d$合成一个

设e,f满足$a*e+b=x$且$c*f+d=x$

联立两个方程,得到$a*e-c*f=d-b$

然后使用exgcd解出e,f,将e,f都乘以$(d-b)/gcd(a,c)$

然后使用一些方法将e,f都变为自然数

然后将e,f代入原方程,变为$x mod (lcm(a,b))=(a*e+b)$即可

注意将e,f变成自然数的过程中要特判0

太菜了,模板题都没有ac

 

7.2

kummer定理

$C^n_{n+m}$含$p$的幂次个数为$n+m$在$p$进制下的进位次数

证明:可以从阶乘中含p的次数和组合数的定义推导出$C^n_{n+m}$含p的幂次数为

(太菜不怎么会latex,图片copy自网络)

注意到上面式子中,$m+n$,$m$,$n$除以$p^i$后,等价于将这些数在p进制下的表示都去掉$i$位

并且发现对于每一个i,$[\frac{m+n}{p^i}]-[\frac{n}{p^i}]-[\frac{m}{p^i}]$的值只可能等于0或1

然后将$n$,$m$去掉$i$位后累加

当去掉i位后,$[\frac{m+n}{p^i}]-[\frac{n}{p^i}]-[\frac{m}{p^i}]$的值为1,那就代表后面的数对现在进位,导致相差为1

所以,每一次进位就对应$[\frac{m+n}{p^i}]-[\frac{n}{p^i}]-[\frac{m}{p^i}]$的值为1,恰好一一对应,得证

例题:

jzoj6170. 【GDSOI 2019 day2】高中生数学题 (难题)

套上一个kummer定理进行dp

毒瘤,我原来想错了3次,暴力dp还不行,得用数学方法推公式优化,极其恶心

细细体会

#include
using namespace std;typedef long long ll;ll n,p,kk,f[100][100][2][2],ans,a[110];int ct;int main(){ freopen("math.in","r",stdin); freopen("math.out","w",stdout); scanf("%lld%lld%lld",&n,&p,&kk); if(p==1){ printf("%lld",n); return 0; } f[0][0][0][1]=1; while(n){ a[++ct]=n%p; n/=p; } reverse(a+1,a+ct+1); for(int i=0;i
代码

 

jzoj5330. 【NOIP2017提高A组模拟8.22】密码 (难题)

比上一道题更加毒瘤

基本思路是,首先高精度除法将n转换为p进制数

枚举状态中,要尝试枚举竖式加法式子下端的数

然后可以计算出竖式最上端的数的范围,同数字取值范围取交集,然后统计答案。。。。

然而不能枚举竖式式子下面的数,因为枚举时间会爆炸。。。。。

然后发现每当下面数+1,一个限定区间会右移一格,于是等差数列求和。。。还要分段计算,根据程序中nv的取值$0,-1,p-1,p$分4种情况讨论。。。。

然后还要滚动数组优化

有毒。。。。。。。。。

细细体会

 

#include
using namespace std;typedef long long ll;#define mo 1000000007llll p,kk,f[2][4010][2][2],ans,a[4010],d[4010],t[100010];char c[100010];int ct;ll mod(){ ll ans=0; for(int i=d[0];i>=1;i--) ans=(ans*10+d[i])%p; return ans;}ll s(ll x){ return (x*(x+1ll)/2ll)%mo;}ll ss(ll x,ll y){ return (s(y)-s(x-1ll)+mo)%mo;}ll div(){ ll ans=0,ok=0,ct=0; for(int i=d[0];i>=1;i--){ ans=(ans*10+d[i]); if(!ok&&ans>=p){ t[++ct]=ans/p; ans%=p; ok=1; } else if(!ok&&ans
View Code

 

转载于:https://www.cnblogs.com/rilisoft/p/10460049.html

你可能感兴趣的文章
页面中公用的全选按钮,单选按钮组件的编写
查看>>
java笔记--用ThreadLocal管理线程,Callable<V>接口实现有返回值的线程
查看>>
(旧笔记搬家)struts.xml中单独页面跳转的配置
查看>>
不定期周末福利:数据结构与算法学习书单
查看>>
strlen函数
查看>>
关于TFS2010使用常见问题
查看>>
Python编译错误总结
查看>>
URL编码与解码
查看>>
Eclipse 安装SVN插件
查看>>
阿里云服务器CentOS6.9安装Mysql
查看>>
剑指offer系列6:数值的整数次方
查看>>
js 过滤敏感词
查看>>
poj2752 Seek the Name, Seek the Fame
查看>>
软件开发和软件测试,我该如何选择?(蜗牛学院)
查看>>
基本封装方法
查看>>
生活大爆炸之何为光速
查看>>
bzoj 2456: mode【瞎搞】
查看>>
[Typescript] Specify Exact Values with TypeScript’s Literal Types
查看>>
[GraphQL] Reuse Query Fields with GraphQL Fragments
查看>>
Illustrated C#学习笔记(一)
查看>>