P10035 「FAOI-R2」Paint

题目背景

小 Y 是一个胖子,他最爱下楼梯了,因为下楼梯很省力气,但是他却有强迫症。

由于刷漆工人 HG 的油漆不够,每一层台阶都只刷了一半——左边或右边,好让小 Y 下楼时不踩到油漆。(众人:这是什么逻辑?

题目描述

整个楼梯共 3N3^N3N 级台阶。

HG 刷漆的规律是:对于从上到下III 级台阶,若 V3(I)V_3(I)V3(I) 是奇数,则刷在左边,否则刷在右边。V3(I)V_3(I)V3(I) 的定义请见提示。

小 Y 因为强迫症,要求自己不能踩到油漆。

现在他来求助你,他最少会踩到油漆多少次?

  • 一次只能下一级台阶。
  • 如果小 Y 站在当前台阶的左边,则他必须站在下一级台阶的右边,反之亦然。
  • 如果油漆在当前台阶左边,那么需要站在当前台阶右边才算没踩到油漆,反之亦然。
  • 小 Y 唯一可以控制的是:他在第 111 级台阶上站在哪边。也就是说,小 Y 只有 222 种下楼梯的方案供选择。

答案对 109+710^9+7109+7 取模。

形式化题意

给定三个 01 串 A,B,CA,B,CA,B,C,长度均为 3N3^N3N。字符串下标从 111 开始。

其中:

  • A=101010101…101A=\texttt{101010101\ldots101}A=101010101101
  • B=010101010…010B=\texttt{010101010\ldots010}B=010101010010
  • C=001001000…C=\texttt{001001000\ldots}C=001001000;具体来说,第 III 个字符为 V3(I) mod 2V_3(I) \bmod 2V3(I)mod2V3(I)V_3(I)V3(I) 的定义请见提示。

mc⁡(X,Y)\operatorname{mc}(X,Y)mc(X,Y) 为字符串 XXXYYY 中匹配的字符的个数。

试求:

min⁡{mc⁡(A,C),mc⁡(B,C)}\min\{\operatorname{mc}(A,C),\operatorname{mc}(B,C)\}min{mc(A,C),mc(B,C)}

答案对 109+710^9+7109+7 取模。

输入格式

本题有多组数据。

第一行,一个正整数 TTT,代表数据组数。

下面 TTT 行,每行一个正整数 NNN

输出格式

每组数据一行,输出踩到油漆的最少次数,即 min⁡{mc⁡(A,C),mc⁡(B,C)}\min\{\operatorname{mc}(A,C),\operatorname{mc}(B,C)\}min{mc(A,C),mc(B,C)}

答案对 109+710^9+7109+7 取模。

输入输出样例 #1

输入 #1

1
1

输出 #1

1

输入输出样例 #2

输入 #2

3
494699
494699494699
494699494699494699

输出 #2

994161775
899186285
348815909

说明/提示

样例 111 解释:

  • A=101A=\texttt{101}A=101
  • B=010B=\texttt{010}B=010
  • C=001C=\texttt{001}C=001
  • mc⁡(A,C)=2\operatorname{mc}(A,C)=2mc(A,C)=2
  • mc⁡(B,C)=1\operatorname{mc}(B,C)=1mc(B,C)=1
  • min⁡{mc⁡(A,C),mc⁡(B,C)}=1\min\{\operatorname{mc}(A,C),\operatorname{mc}(B,C)\}=1min{mc(A,C),mc(B,C)}=1

测试点编号 T≤T \leT N≤N \leN 分值
111 101010 101010 505050
222 10510^5105 101810^{18}1018 505050

对于 100%100\%100% 的数据,1≤T≤1051 \le T \le 10^{5}1T1051≤N≤10181 \le N \le 10^{18}1N1018

提示: V3(X)V_3(X)V3(X)XXX 中质因数 333 的个数。例如,V3(14)=0V_3(14)=0V3(14)=0V3(18)=2V_3(18)=2V3(18)=2

C++实现

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
inline ll read() {
	ll x = 0, f = 1; char ch = getchar();
	while(ch < '0' || ch > '9') { if(ch == '-') f = -1; ch = getchar(); }
	while(ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar(); }
	return x * f;
}
const ll mod = 1000000007;
ll T;
inline ll power(ll a, ll b) {
	ll ans = 1;
	while(b) {
		if(b & 1) ans = (ans * a) % mod;
		a = (a * a) % mod;
		b >>= 1;
	}
	return ans;
}
signed main() {
    T = read();
    while(T--) {
        ll x = read(); x %= mod - 1;
        ll a = power(3, x) - 1;
        printf("%lld\n", ((a & 1) ? a + mod : a) / 2);
    }
    return 0;
}

在这里插入图片描述

后续

接下来我会不断用C++来实现信奥比赛中的算法题、GESP考级编程题实现、白名单赛事考题实现,记录日常的编程生活、比赛心得,感兴趣的请关注,我后续将继续分享相关内容

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐