const int N = 1e9;
int p[1010], cnt;
bool vis[1010];
unordered_set<int> st;
char s[205];
ll pri[] = { 2,3,5,7,11,13 };
vector<int> g[6];
ll a[6];
void get() {
f(i, 2, 1009) {
if (!vis[i])p[++cnt] = i;
for (int j = 1;p[j] <= 1009 / i;j++) {
vis[p[j] * i] = true;
if (i%p[j] == 0)break;
}
}
}
void get_2() {
for (int j = p[cnt];j*j <=N;j++) {
for (int i = j * j;i <= N;i += j * j)st.insert(i);
}
}
bool check(int a, int b) {
for (int i = 0;b + i * a < 200;i++) {//%a==b,情况
if (s[b + i * a] == '1')return false;
}
return true;
}
pair<ll,ll> china(int n, ll *a, ll *m) {
ll M = 1, ret = 0;
for (int i = 0; i < n; i++) M *= m[i];
for (int i = 0; i < n; i++) {
ll w = M / m[i];
ret = (ret + w * inv(w, m[i]) * a[i]) % M;
}
return pair<ll,ll>{ (ret + M) % M,M };
}
bool ch2(int x) {//无平方因子则false
f(i, 1, cnt) {
if (x % (p[i] * p[i]) == 0)return true;
}
return st.count(x);
}
bool ch1(int st) {
f(i, 0, 199) {
if (s[i]=='0'&&!ch2(st + i))return false;
else if (s[i] == '1'&&ch2(st + i))return false;
}
return true;
}
ll cal() {
//检查满足当前的组合等价类
pair<ll, ll> t = china(6, a, pri);
if (ch1(t.first))return t.first;
if ((t.first + t.second + 199) <= N && ch1(t.first + t.second))return { t.second + t.first };
//debug((2e18));
return 2e18;
}
ll ans = 2e18;
void dfs(int x) {
if (x == 6) {
ans = min(ans, cal());
return;
}
else {
for (auto i : g[x]) {
a[x] = i;
dfs(x + 1);
}
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif
//1e9!!!!!!!是不是很神奇?
//题意:现在已知一个长度为200的字符串t可能是,1到1e9的数的莫比乌斯函数绝对值
//构成的字符串的子串
//问你是否可能是s的子串,如果可能输出在s中第一次出现的位置。
//因为这里的u函数取了绝对值,我们的关注点放在一个数是否有平方因子,
//即有素数因子的次数大于等于2,如果有就是0,否则就是1
//一开始,我们会发现这道题完全没有突破口,因为这道题的范围实在是太大了
//1.首先,我们需要知道的是如何高效求1e9范围内的一个数是否有平方因子
//首先直接预处理1e9质数必死,那么考虑我们的枚举倍数算法,n*logn,显然
//还是用不了的,那么牛逼的操作就来了考虑先对小部分小的质数直接暴力判断
//然后从一个较大的质数开始,枚举它的平方,以及它的平方的倍数这样每次只要169+log(6e5)
//2.但是关键的问题还是没解决,如何在1e9内找一个长度为200的子串呢
//牛逼的思想又来了,其实问题的关键在于确定我们子串的开始位置
//我们可以发现如果我们将1e9的数按模4的意义分类,首先我们可以直接判断以这个
//模意义下的数开头的数是否是可以有解的,无解就直接干死,因为假如我们pos为4的
//倍数,那么pos+4的位置也是4的倍数,我们拿这个值去与原子串比较判断,如果
//这个都不行,表明以%4为某个数的数开头是必定无解的,这样我们就起到了剪枝
//有意义的话就从小的到大枚举等价类,4->8->12,我们发现这个过程也是很漫长的
//能不能再优化呢,于是乎骚操作来了,无敌优美的凹曲线。
//我们光考虑一个2*2,发现等价类还是很多,那么就多几个质数,使得等价类变少
//901800900,当我们取到6个质数时就会发现,我们最多只需要算两次等价类
//ok大致思路确定正确后,就可以处理出题目给我们的t对这6个质数的哪些模意义下
//有解把,6个质数的莫意义最多有30030种组合,对于每种组合我们要去判断200个数
//每次判断内部大概也需要169+log(6e5)去检查,当然这是最最最坏的情况,感性的来说
//你不给这复杂度除个10?哦,3e8那就可以过了
//ll lcm = 1ll * 4 * 9 * 25 * 49 * 121 * 169;
get();//169
get_2();//6e5
f(i, 1, 10) {
scanf("%s", s + (i-1) * 20);//0-199
}
f(i, 0, 5)pri[i] *= pri[i];
f(i, 0, 5){
f(j, 0, pri[i] - 1) {//检查在模每个质数意义下是否成立
if (check(pri[i], j))g[i].emplace_back(pri[i]-j);
}
}
int num = 0;
f(i, 0, 199) {
if (s[i] == '0')num++;
}
if (num >= 100) {
puts("-1");
return 0;
}
/*f(i, 0, 5) {
for (auto u : g[i])cout << u << " ";
cout << endl;
}*/
//减掉了一些必死的模意义组合
//开始枚举每种组合
dfs(0);
if (ans == 2e18)puts("-1");
else cout << ans << endl;
return 0;
}
03-02
507
07-10
303
“相关推荐”对你有帮助么?
-
非常没帮助
-
没帮助
-
一般
-
有帮助
-
非常有帮助
提交