• 模拟赛3 题解


    爆灵力……


    CF995E Number Clicker

    很有意思的题。
    算法一:双向广搜
    据说状态数最多 (10^7),可过。
    算法二:随机化
    首先介绍一个前置理论:生日攻击
    这个理论最通俗的描述是说,(23) 个人中有两个人生日相同的概率超过 (50\%)(假设一年有 (365) 天),(70) 个人时概率为 (99.9\%),而在人数达到 (200) 时,概率已经非常逼近 (100\%)(准确说是 (1-2 imes 10^{-29}))。
    这个理论常用于哈希碰撞攻击。形式化地,对于一个值域范围为 (n) 的整值函数,设其定义域范围为 (k) 时出现相同值的概率为 (p),则有

    [p=1-overline{p}=1-frac{n^{underline{k}}}{n^k} ]

    其中 (n^{underline{k}})(n)(k) 次下降幂。
    解出这个方程可得:当 (k>sqrt{frac{pi}{2}n}) 时,(p>50\%)(具体做法康这里)。
    所以我们只需为 (u,v) 分别随机生成 (sqrt{p}) 条长度为 (100) 的操作路径即可求解,复杂度 (O(sqrt{p}log p))
    算法三:这叫啥啊我也不知道
    期望更优的方法,很神奇。
    考虑为 (u,v) 分别生成一个到 (0) 的操作路径,具体方法是随机取一个整数 (xin [1,p-1]),记 (aequiv uxpmod p,b=x),对 ((a,b)) 使用更损相减术迭代至 (b=0)。考虑这么做的意义,由于 (uequivdfrac{a}{b}pmod p),那么减一操作相当于 (dfrac{a}{b} o dfrac{a-b}{b}pmod p),求逆操作相当于 (dfrac{a}{b} odfrac{b}{a}pmod p) 太神奇了!
    (v) 同理,由于操作可逆,所以只需将 (v) 的操作中所有的减换成加即可。
    当然在实际实现中我们得先用辗转相除计算路径长度,如果小于 (100) 再用更损相减。
    官方题解说这个做法“It happens to take a few steps in most cases, but we have no proof.”
    (代码跑了 0ms,我惊了

    #include <bits/stdc++.h>
    using namespace std;
    mt19937 rng(1919810);
    
    const int N=105;
    int u,v,p,s1[N],s2[N];
    
    int gcd(int a,int b) {return b?gcd(b,a%b)+a/b+1:0;}
    
    int solve(int n,int s[])
    {
    	int a,b,cnt=0;
    	do b=rng()%(p-1)+1,a=1LL*b*n%p;
    	while(gcd(a,b)>100);
    	while(b)
    		if(a<b) s[++cnt]=3,swap(a,b);
    		else s[++cnt]=2,a-=b;
    	return cnt;
    }
    
    int main()
    {
    	scanf("%d%d%d",&u,&v,&p);
    	int len1=solve(u,s1),len2=solve(v,s2);
    	printf("%d
    ",len1+len2);
    	for(int i=1;i<=len1;++i) printf("%d ",s1[i]);
    	for(int i=len2;i;--i) printf("%d ",s2[i]==2?1:3);
    	return 0;
    }
    

    CF300D Painting Square

    这道题 CF 上 (k<1000),所以可以不用 NTT 水过,但毒瘤把数据加强到 (k<50000) 了,只能用 NTT 了 555……
    还没学 NTT,先把式子放到这吧(早晚会学的,口亨~)。
    先考虑一个显然的 DP,记 (f_{i,j}) 表示边长为 (2^i+1) 的正方形切 (j) 刀的方案数,有

    [f_{i,j}=sum_{a+b+c+d=j-1}f_{i-1,a}f_{i-1,b}f_{i-1,c}f_{i-1,d} ]

    (g_{i,j}=sumlimits_{a+b=j}f_{i,a}f_{i,b}),则 (f_{i,j}=sumlimits_{a+b=j-1}g_{i-1,a}g_{i-1,b})
    直接算 (O(k^2log n)),NTT 优化后 (O(klog klog n))

    CF724E Goods Transportation

    部分分有一个显然的网络流,由于 (n<10000) 过不了。
    联想到最大流=最小割,又由于本题的图建得非常特殊,所以联想到要用 DP 模拟最小割。记 (f_{i,j}) 表示前 (i) 个点其中有 (j) 个点属于 (S) 集时的最小割。分别讨论 (i) 属于 (S) 集与 (T) 集的情况,如果属于 (S) 集,则最小割加 (s_i),否则最小割加 (p_i+j imes c)。注意需要滚动数组。
    (O(n^2))(10000) 可还行(发抖

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N=1e4+5;
    int n,c,p[N],s[N];
    long long f[2][N];
    
    int main()
    {
    	scanf("%d%d",&n,&c);
    	for(int i=1;i<=n;++i) scanf("%d",p+i);
    	for(int i=1;i<=n;++i) scanf("%d",s+i);
    	for(int i=1;i<=n;++i)
    	{
    		memset(f[i&1],0x3f,sizeof(f[i&1]));
    		for(int j=0;j<=i;++j)
    		{
    			f[i&1][j]=f[(i^1)&1][j]+p[i]+1LL*j*c;
    			if(j) f[i&1][j]=min(f[i&1][j],f[(i^1)&1][j-1]+s[i]);
    		}
    	}
    	printf("%lld
    ",*min_element(f[n&1],f[n&1]+n+1));
    	return 0;
    }
    
  • 相关阅读:
    【转】禁用chrome firefox 的 WebRTC功能防止真实IP泄漏
    这是我的主场
    【转】反编译获取任何微信小程序源码(完)
    【转】npm 安装express npm ERR! code UNABLE_TO_VERIFY_LEAF_SIGNATURE
    查询最新的邮编地区
    【转】汇编语言入门教程
    Microsoft Windows远程桌面协议中间人攻击漏洞(CVE-2005-1794)漏洞解决方案(Windows server2003)
    IIS隐藏版本号教程(Windows Server 2003)
    Windows Server 2003添加防火墙策略教程
    Tomcat禁用SSLv3和RC4算法
  • 原文地址:https://www.cnblogs.com/wzzyr24/p/12771267.html
Copyright © 2020-2023  润新知