在这片梦想之地,不堪回首的过去像泡沫一样散去,不|

PassName

园龄:3年1个月粉丝:32关注:16

ARC166

ARC166

前言

到了 e 难度莫名陡增.......

[ARC166A] Replace C or Swap AB

一个比较简单的贪心

进行交换操作肯定会减少 C 的个数。并且唯一可以变序位置的操作是操作三,所以最后结果一定是 B 尽可能在前。等价于把某个 A 向后移一个位置。贪心地把靠前的 C 都替换成 A。判断当前 X 中是否每个对应的 A 所在位置都不大于它在 Y 中的目标位置即可。

signed main() 
{
    int T;
    cin >> T;
  
    while (T--) 
	{
        int n; string x, y;
        cin >> n >> x >> y;
        deque<int> q;
        bool flag = 0;

        for (rint i = 0; i < n; i++) 
		{
            if (y[i] == 'C') 
			{
                if (x[i] != 'C') 
				{
                    puts("No");
                    flag = 1;
                    break;
                } 
				else q.push_back((int)i);
            }
        }

        if (flag) continue;
        int cnt = 0;
        q.push_back(n);

        while (!q.empty()) 
		{
            int a = q.front();
            q.pop_front();
            int a1 = 0, c1 = 0;

            for (rint i = cnt; i < a; i++) 
			{
                if (x[i] == 'A') a1++;
                if (x[i] == 'C') c1++;
                if (y[i] == 'A') 
				{
                    if (!a1 && !c1) 
					{
                        puts("No");
                        flag = 1;
                        break;
                    }
                    if (!a1) c1--;
                    else a1--;
                }
            }
            if (flag) break;
            if (a1 > 0) 
			{
                puts("No");
                flag = 1;
                break;
            }
            cnt = a + 1;
        }
        if (flag) continue;
        puts("Yes");
    }

    return 0;
}

[ARC166B] Make Multiples

传送门link

直接 dp,其实可以不用状态压缩 dp

f[i][0/1][0/1][0/1] 表示前 i 个数是否有 a,b,c 的倍数

预处理出来每个数变成某个数的倍数要加上多少然后直接转移

int lcm(int a, int b) {return a * b / __gcd(a, b);}

signed main() 
{
    cin >> n >> x >> y >> z;

    for (rint i = 1; i <= n; i++) 
	{
        int t;
		cin >> t;
        a[i] = x - (t - 1) % x - 1;
        b[i] = y - (t - 1) % y - 1;
        c[i] = z - (t - 1) % z - 1;
        ab[i] = lcm(x, y) - (t - 1) % lcm(x, y) - 1;
        bc[i] = lcm(z, y) - (t - 1) % lcm(z, y) - 1;
        ac[i] = lcm(x, z) - (t - 1) % lcm(x, z) - 1;
        abc[i] = lcm(lcm(x, y), z) - (t - 1) % lcm(lcm(x, y), z) - 1;
    }

    memset(f, 0x3f, sizeof f);
    f[0][0][0][0] = 0;

    for (rint i = 1; i <= n; i++) 
	{
        f[i][0][0][0] = f[i - 1][0][0][0];
        
        f[i][0][0][1] = min(f[i - 1][0][0][1], f[i - 1][0][0][0] + c[i]);
        f[i][0][1][0] = min(f[i - 1][0][1][0], f[i - 1][0][0][0] + b[i]);
        f[i][1][0][0] = min(f[i - 1][1][0][0], f[i - 1][0][0][0] + a[i]);
        
        f[i][0][1][1] = min({f[i - 1][0][1][1], f[i - 1][0][0][1] + b[i], f[i - 1][0][1][0] + c[i], f[i - 1][0][0][0] + bc[i]});
        f[i][1][0][1] = min({f[i - 1][1][0][1], f[i - 1][0][0][1] + a[i], f[i - 1][1][0][0] + c[i], f[i - 1][0][0][0] + ac[i]});
        f[i][1][1][0] = min({f[i - 1][1][1][0], f[i - 1][1][0][0] + b[i], f[i - 1][0][1][0] + a[i], f[i - 1][0][0][0] + ab[i]});
        
		f[i][1][1][1] = min({f[i - 1][1][1][1], f[i - 1][1][1][0] + c[i], f[i - 1][1][0][1] + b[i], f[i - 1][0][1][1] + a[i], f[i - 1][0][0][1] + ab[i], f[i - 1][0][1][0] + ac[i], f[i - 1][1][0][0] + bc[i], f[i - 1][0][0][0] + abc[i]});
    }

    cout << f[n][1][1][1] << endl;
    
    return 0;
}

[ARC166C] LU / RD Marking

传送门link

将边转化成点的问题,染色就是染 (i,j)(i+1,j1) 位置的点

将点连边。因为染色方式只有一种,所以这个点阵构成了若干条互不相关的斜向的链。

答案是这些链的方案的乘积。

考虑一条边数为 n 的链。限制为相邻的边不能同时选。

fi 表示前 i 条边的方案,因为第 i 条边若不选,则方案为 fi1,第 i1 条边选不选都无所谓,fi=fi1+fi2。若第 i 条边选,则第 i1 条边一定不能选,所以从 fi2 转移过来。初始态为 f0=1,f1=2(即斐波那契数列)

一个矩形切割出的若干条链的边数是形如 1,3,5,7,8,8,8,8,7,5,3,1 这样的。对于左右两边可以求一个 f 序列奇数位的前缀积,中间部分就快速幂。

复杂度 O(n+Tlogn)

signed main()
{
	f[0] = 1;
	f[1] = s[1] = 2;
	for (rint i = 2; i < N; i++) f[i] = (f[i - 1] + f[i - 2]) % mod;
	for (rint i = 3; i < N; i++)
	{
		if (!i % 2) continue;
		s[i] = s[i - 2] * f[i] % mod;
	}
	cin >> T;
	while (T--)
	{
		cin >> n >> m;
		if (n > m) swap(n, m);
		cout << s[2 * n - 1] * s[2 * n - 1] % mod * qpow(f[2 * n], m - n) % mod << endl;
	}
	return 0;
}

[ARC166D] Interval Counts

传送门link

假设当前已经满足了 1i1 的限制,维护一个队列表示当前还没确定右端点的所有左端点。

如果 yi=yi1,让原来右端点接在 xi1 的区间接到 xi

如果 yi>yi1,原来的区间就算全部接到 xi 上仍然不够,需要再加 yiyi1 个左端点为 xi1+1 的区间。

如果 yi<yi1,说明要删掉 yi1yi 个区间,由于要让最小值最大,所以需要删掉左端点最小的区间。

于是只维护一个左端点递增的区间,区间数很多,记录这个左端点的个数。

复杂度 O(n)

int n;
int x[N], y[N];
int ans = inf;
struct node
{
	int x, y;
}q[N];

signed main() 
{
	cin >> n;
	for (rint i = 1; i <= n; i++) cin >> x[i];
	for (rint i = 1; i <= n; i++) cin >> y[i];
	
	x[0] = -inf;
	int head = 1, top = 0;
	
	for (rint i = 1; i <= n; i++) 
	{
		if (y[i] > y[i - 1]) 
		{
			q[++top] = {x[i - 1] + 1, y[i] - y[i - 1]};
		} 
		if (y[i] < y[i - 1]) 
		{
			int delta = y[i - 1] - y[i];
			while(delta && head <= top)
			{
				int w = min(q[head].y, delta);
				delta -= w;
				q[head].y -= w;
				ans = min(ans, x[i] - 1 - q[head].x);
				if (!q[head].y) head++;
				else break;
			}
		}
	}
	
	if (ans >= inf) cout << -1 << endl;
	else cout << ans << endl;
	
	return 0;
}

[ARC166E] Fizz Buzz Difference

传送门link

在解决这个题目之前,需要学习一个东西。

如何求解线性同余不等式。

给定 l,r,a,m(l,r,a[0,m),lr),求最小非负整数 x 满足:laxmodmr

尝试将问题转化为一个更小规模的问题 laxkmr

其中 k=axm

如果在 [l,r] 之间找到一个 a 的倍数,即 raal,这意味着 k 可以取到最小值 0。同时,我们直接找到 x 的一个解:la

关于此解的最小性,只看左侧不等式,我们有 x 是合法解的必要条件 axl+km,即 xmk+la,显然此下界关于 k 是单调递增的,而此解恰好取到了最小下界,故一定是最小的可能合法解,而其合法性显然。

否则,将上式进一步整理为 axrkmaxl

由于 [l,r] 之间没有 a 的倍数,设 l=pa+u,r=pa+v,有:a(xp)vkma(xp)u

上式对 a 取模可得:rmodakmmodalmoda

尝试说明当找到该式中 k 的最小可行解时就能唯一确定 x 的最小可行解。首先一个原式中可行的 x 一定对应一个该式中可行的 k,并且对应关系是单调的,即更小的 x 对应于不会更大的 k,因此我们找到的最小可行 k 最小可行 x 对应的 k。同时,对于一个满足上式的 k0,容易验证一定有 x0=km+ra 是原式的可行解,且恰好取到下界。

问题转化为求解 k,即 (rmoda,lmoda,mmoda,a) 的新问题,问题规模减小,不断递归调用

Code:

int solve(int l, int r, int a, int m) 
{
	if (l > r || !a) return -1;
	if (!l) return 0;
	if (r / a * a >= l) return (l - 1) / a + 1;
	int k = solve((a - r % a) % a, (a - l % a) % a, m % a, a);
	return k == -1 ? -1 : (m * k + l - 1) / a + 1;
}

现在再来处理这道题目。

假设现在这个合法区间是 [L0,R0],将 R0 不断 1 得到一系列区间,它们的 nanb 取值一定恰好覆盖 [1,n]。因此 n[1,n] 中限制最严格的,将题目限制修改为 nanbn

合法区间一定满足 aL1,aR+1,否则可以将端点外移让区间长度变长且 nanb 不会变大。设 L=ak1+1,R=ak21(k1<k2),首先来最大化 RL,即最大化 x=k2k1

确定 x 后,na=x1,因此需最大化 nb

一旦确定区间中第一个 b 的倍数的位置 pos,那么 nb 也唯一确定,故只需要最小化 posL

g=gcd(a,b),那么 posL 最小能恰好取到 g1。因此,确定 x 后可以直接求得最小可能 nanb,且此值关于 x 具有单调性。二分即可。

记求得的最大 xX,此时区间内至少需要出现 c=X1nb 的倍数。此限制可以表示为 RLRmodbb(c1),即 (L+aX2)modb[0,aX2b(c1)],如果 aX2b(c1)b,这意味着这条限制不存在,直接令 L=1;否则问题可以转化成 ak1modb(1aX)modb,求最小合法 k1。刚才上面那个代码就可以快速解决。

复杂度 O(TlogV)


int solve(int l, int r, int a, int m) 
{
	if (l > r || !a) return -1;
	if (!l) return 0;
	if (r / a * a >= l) return (l - 1) / a + 1;
	int k = solve((a - r % a) % a, (a - l % a) % a, m % a, a);
	return k == -1 ? -1 : (m * k + l - 1) / a + 1;
}

signed main() 
{
	int T;
	cin >> T;
	while (T--) 
	{
		cin >> n >> a >> b;
		int g = __gcd(a, b);
		int l = 1, r = inf, res;
		while (l < r) 
		{
			int mid = (l + r) >> 1;
			if (mid - 2 - (a * mid - 1 - g) / b > n) r = mid;
			else l = mid + 1, res = mid;
		}
		int tmp = solve(((1 - a * res) % b + b) % b, b - 1, a, b);
		cout << tmp * a + 1 << " " << (tmp + res) * a - 1 << endl;
	}
	return 0;
}

[ARC166F] Tangent Addition Formula

传送门link

一道不可做的题,看的第一篇题解。懂了但没有完全懂。。。。

t 的性质二 x,yN,t(x+y)(1t(x)t(y))t(x)+t(y)(modp) 目前没法入手解决,记标记为式 ()

带入 x=0,y=0,得到 t(0)(1t(0)2)2t(0)(modp),解得 t(0)=0t(0)21(modp)。设 I21(modp),即模 p 意义下虚数单位,则 t(0){I,I,0}

t=(0,0,0,) 满足 (),说明 b=0t 存在。

由和角公式 tan(x+y)=tan(x)+tan(y)1tan(x)tan(y),对比 (),对比可得移了项少了取模。t(x) 就是某种模意义下的正切函数。

首先展开 tan(x)=sin(x)cos(x)

根据欧拉公式 eix=cos(x)+isin(x),得到 sin(x)=eixeix2i,cos(x)=eix+eix2

相除得到 tan(x)=1(e2i)x1+(e2i)x×i

形式上 tan(x) 形如 1rx1+rxi

【结论 1】

t(x) 形如 1rx1+rxI,其中 I21(modp)

证明:将该式带入 (),得到:

t(x+y)(1t(x)t(y))=1rx+y1+rx+yI(11rx1+rxI1ry1+ryI)

利用 I21(modp),得到 1rx+y1+rx+yI(1+(1rx)(1ry)(1+rx)(1+ry))(modp)

将分子分母去括号并通分,得到 1rx+y1+rx+yI2(1+rx+y)1+rx+ry+rx+y(modp)

约分,分解因式,得 I(1+rx)(1ry)+(1rx)(1+ry)(1+rx)(1+ry)(modp)

拆开分子,得 1ry1+ryI+1rx1+rxI(modp)

再代回去 t(x)+t(y)(modp)

左边同余于右边,() 成立。原命题得证。

上面除了 I21(modp) 都是恒等变换,因此原问题变成了和 I 相关的问题。而这个式子,就是二次剩余。

暂记模 p 意义下的整数域为 Zp

讨论 p=2

b=0,则可以有 t=(0,0,0,) 满足 ()

b=1,则可以有 t=(1,1,1,) 满足 ()

由于这两种数列的取值和项数无关,对于所有 a 都能这样取

因此,此时 t 存在。

讨论 p1(mod4)

【结论 2】

p1(mod4)IZp,I21(modp),其中 p 为奇质数。

证明:

p 的最小正原根为 g。由原根存在性定理,g 存在。

gp11(modp)g 可视为 Zpp1 次单位根。由 I41(modp)I 可视为 Zp4 次单位根。

因此有 I=gp14。若 I 存在,则 p14Z,即 4|p1

故若 I 存在,则 p1(mod4),必要性得证。

对于充分性,取 Igp14(modp),满足题意。

原命题得证。

既然如此,再结合上 t(0){I,I,0},我们继续分类。

接下来。所有结论都有前提条件 p1(mod4)

讨论 t(1){I,I}

【结论 3】

t(1){I,I},则 xN+,t(x)=t(1)

数学归纳法,当 x=1 时显然相等。

现在假设当 x=nN+ 时成立,即 t(n)=t(1),下证当 x=n+1 时成立。

t(n+1)(1t(n)t(1))t(n)+t(1)(modp)

代入 t(n)=t(1),得 t(n+1)(1t(1)2)2t(1)(modp)

代入 t(1)21(modp),两边同时除以 2,得到 t(n+1)=t(1)

原命题得证

由此可得,本类的合法 t 有且仅有六种情况

t=(I,I,I,I,)

t=(I,I,I,I,)

t=(0,I,I,I,)

t=(0,I,I,I,)

t=(I,I,I,I,)

t=(I,I,I,I,)

讨论 t(1){I,I}

【结论 4】

t(1){I,I},则 t(0)=0

证明:考虑证明其逆否命题,即若 t(0)0,则 t(1){I,I}

x=0,y=1 代入 (),得到 t(1)(1t(1)t(0))t(1)+t(0)(modp)

化简得到 (t(1)2+1)t(0)0(modp)

因为 t(0)0,两边同时除以 t(0),移项得 t(1)21(modp)

解得 t(1){I,I}

原命题得证

将特值代入 () 也起不了效果了,只能求助结论 1 了

由于分母不能为 0,所以要求 xN,rx1(modp)。如果存在 rZp,则 t 存在,否则 t 不存在

由性质三:t(a)=b。列方程 b1ra1+raI(modp)

化简得到 raIbI+b(modp),是个模为质数的高次剩余方程,原根加 BSGS 就能解

在本分类下,t 存在当且仅当存在 r{r|raIbI+b(modp)} 使得 xN,rx1(modp)

讨论 p3(mod4)

在普通的模意义下整数域上没有

但是高斯整环 Z(i) ???

不妨记模 p 意义下高斯整环为 Z(i)p={a+bi|a,bZp},不难得出这玩意是个有限域。

在强行添加上虚数单位后,讨论 t 的存在条件。

由于对于所有 xZp 可以看作 x+0iZ(i)p,因此 ZpZ(i)p

依题有 t(x)=1rx1+rxiZp,因此 rZ(i)p 应该满足 xN,1rx1+rxiZprx1(modp)

判断属不属于集合还是太麻烦了。能不能转化一下?当然可以。我们有如下结论:

【结论 5】

xN,1rx1+rxiZprp+11(modp)

证明:根据二项式定理有 (x+y)pxp+yp(modp)。(仅有 (p0)(pp) 不能被 p 整除,其余均含因数 p。)

z=x+yiZp,则 zpxp+(yi)p(modp)

由于 p3(mod4),有 ip=i,因此 zpxpypi(modp)

根据费马小定理,xpx(modp),所以 zpxyi(modp)

当且仅当 y=0,即 zZp 时,z=xyi

zZpzpz(modp)

代入 z=1rx1+rxi,原命题可转化为
(1rx1+rxi)p1rx1+rxi(modp)rp+11(modp)

移项有 (1rx1+rxi)p1rx1+rxi0(modp)

拆括号,得到 (1rx)p(1+rx)pi1rx1+rxi0(modp)

两边同乘 1i,得:(1rx)p(1+rx)p+1rx1+rx0(modp)

用上面二项式定理的推论展开幂次,得 1rxp1+rxp+1rx1+rx0(modp)

通分,得 1(rp+1)x1+rx+rpx+r(p+1)x0(modp)

去分母,移项,得 (rp+1)x1(modp)

由于该式对于所有 x 均成立,可以去掉指数,得 rp+11(modp)

充分性得证。以上各式均为恒等变换,反过来可证明必要性 原命题得证。

和上面同样解方程 b1ra1+rai(modp),解得 raibi+b(modp)

不知道原根存在性,没办法 BSGS

Z(i)p 是个有限域吗

这个域共有 p2 个元素,根据有限域的存在性和唯一性,其为有限域 Fp2

【结论 6】

(有限域原根存在性)
有限域 F 存在元素 g 使得 gn=1,F={gt|0t<n}

综合上述讨论,我们最终得到 t 的存在性判定方式

p=2b=0b21(modp) 时,t 存在

否则,若 t 存在,则存在 r 满足以下三个条件

rau(modp)

rv1(modp)

xN,rx1(modp)

其中 u=ibi+b,i21(modp),v={0amp;(p1(mod4))p+1amp;(p3(mod4))

记循环群大小 n={p1amp;(p1(mod4))p21amp;(p3(mod4))

rgt(modp),则 rvgtv1(modp)

gn1(modp),得到 n|tv,因此有 ngcd(n,v)|t

同理,由 rx1(modp)g2tx1(modp)

因此 txn2(modn)。这玩意可以继续除下去直到 n 中的 2 因数被除干净

2m|n,2m+1n,则可以推出 2m|t

所以 t 的一个取值是 lcm(ngcd(n,v),2m)

不妨就令 t 为该值。则再设 rgtk

还差条件一,代入 rgatku

再和上面一样的做法,得出 ungcd(at,n)=1

复杂度 O(Tlogp)

int qpow(int a, int b)
{
	int res = 1;
	while (b)
	{
		if (b & 1) res = res * a % p;
		b >>= 1;
		a = a * a % p;
	}
	return res;
}

struct complex 
{
	int X, Y;
	bool operator == (complex x) {return X == x.X && Y == x.Y;}
	complex operator * (complex x)
	{
		complex s;
		s = (complex) {X * x.X % p + imod * x.Y % p * Y % p, Y * x.X % p + X * x.Y % p};
		if (s.X >= p) s.X -= p; 
		if (s.Y >= p) s.Y -= p;
		return s;
	}
	complex operator ^ (int b) 
	{
		complex s({1, 0}), a(*this);
		while (b) {if(b & 1) s = s * a;a = a * a;b >>= 1;}
		return s;
	}
};

signed main() 
{
	cin >> T;
	while (T--)
	{
		cin >> p >> a >> b;
		
		if (p == 2 || b == 0 || b * b % p + 1 == p) 
		{
			puts("Yes");
			continue;
		}
		
		if ((p & 3) == 1) 
		{
			n = p - 1;
			int f, l;
			
			do 
			{
				l = rand() % p;
				imod = l * l % p - (p - 1);
				imod < 0 && (imod += p);
			} 
			
			while (!l || qpow(imod, (p - 1) >> 1) == 1);
			f = ((complex) {l, 1} ^ ((p + 1) >> 1)).X;
			if (p - f < f) f = p - f;
			int t = n / (n & (-n));
			t /= __gcd(a, t);
			
			int u = (f - b) * qpow(f + b, p - 2) % p;
			if (u < 0) u += p;
			if (qpow(u, t) == 1) puts("Yes");
			else puts("No");
		} 
		
		else 
		{
			n = p * p - 1;
			imod = p - 1;
			
			int t = n / ((n & (-n)) / __gcd((n & (-n)), p - 1) * (p - 1));
			t /= __gcd(a, t);
			int inv = qpow(b * b % p + 1, p - 2);
			complex u = {(1 - b * b % p + p) * inv % p,  (b << 1) % p * inv % p}; 
			
			if ((u ^ t) == (complex){1, 0}) puts("Yes");
			else puts("No");
		}
	}
	
	return 0;
}

本文作者:PassName

本文链接:https://www.cnblogs.com/spaceswalker/p/17976480

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   PassName  阅读(32)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起