所以这是几天前我在网上比赛中遇到的挑战之一的问题。
问题:
接受两个输入。
在每个问题中,你必须找出索引 L i 之间字符串形成的数字> 和 R i 可被整除7或不。
输入:
第一行包含 N 数字所包含的数字。下一行包含 Q ,表示问题的数量。每个 Q 行包含2个整数 L i < / sub>和 R i 。
输出:
对于每个问题,如果索引 L i之间的字符串形成的数字,则打印“YES”或“NO” 和 R i 被7整除。
约束:
1≤N≤10 5
1≤Q≤10 5
1≤L i ,R i ≤N
示例输入:
357753
3
1 2
2 3
4 4
示例输出:
是
不
是的
解释
对于第一个查询,数字将为35,显然可以被7整除。
每个输入文件的时间限制: 1.0秒。
内存限制: 256 MB
来源限制: 1024 KB
我的方法:
现在根据约束,数字的最大长度,即 N 可以达到 10 5 。这个大数字不能适用于数字数据结构,我很确定这不是有效的方法。
首先尝试:
我想到了这个算法,将通用的除法规则应用于数字的每个数字。这将在线性时间内检查任意两个数字之间的可分性,即 O(N)。
static String isDivisibleBy(String theIndexedNumber, int divisiblityNo){
int moduloValue = 0;
for(int i = 0; i < theIndexedNumber.length(); i++){
moduloValue = moduloValue * 10;
moduloValue += Character.getNumericValue(theIndexedNumber.charAt(i));
moduloValue %= divisiblityNo;
}
if(moduloValue == 0){
return "YES";
} else{
return "NO";
}
}
但在这种情况下,算法还必须循环遍历 Q 的所有值,这些值也可以高达 10 5 。
因此,解决问题所需的时间变为 O(Q.N),也可以视为二次时间。因此,这超过了给定的时间限制,效率不高。
第二次尝试:
在此之后无效,我尝试搜索 divisibility rule of 7 。我发现的所有内容都涉及基于数字的每个数字的计算。因此,这将再次导致线性时间算法。因此,结合问题的数量,它将相当于二次时间,即O(Q.N)
我确实找到了一个名为 Pohlman-Mass可分解方法的算法7 ,这表明
使用快速交替添加和减法:
42,341,530 - &GT; 530-341 = 189 + 42 = 231 - &gt; 23 - (1×2)= 21是
但所有这一切都是,将时间设为1/3 Q.N,这没有多大帮助。
我在这里遗漏了什么吗?任何人都可以帮我找到解决这个问题的方法吗?
此外,这是否有可能是动态编程问题?
答案 0 :(得分:2)
基本上你希望能够在给定任意点数的mod的情况下计算任何数字的mod 7.
你可以做的是;
e.g。介于2和3之间
357 % 7 = 0
3 % 7 = 3 and 300 % 7 = 6 (the distance between the start and end)
和0!= 6所以数字不是7的倍数。
介于4和4之间
3577 % 7 == 0
357 % 7 = 0 and 0 * 10 % 7 = 0
为0 == 0它是7的倍数。
答案 1 :(得分:2)
有两种方法可以解决这个问题。
1:动态规划方法
让输入为数字A[N]
数组
让N[L,R]
为数字L to R
形成的数字
让另一个数组为M[N]
,其中M[i] = N[1,i] mod 7
所以M[i+1] = ((M[i] * 10) mod 7 + A[i+1] mod 7) mod 7
预先计算数组M
。
现在考虑表达。
N[1,R] = N[1,L-1] *
10 R-L + 1 + N[L,R]
implies (N[1,R] mod 7) = (N[1,L-1] mod 7 *
(10 R-L + 1 mod 7)) + (N[L,R] mod 7)
implies N[L,R] mod 7 = (M[R] - M[L-1] *
(10 R-L + 1 mod 7)) mod 7
N[L,R] mod 7
给出了答案,可以在O(1)
中计算,因为表达式右侧的所有值都已存在。
对于10 R-L + 1 mod 7
,您可以为10的所有幂预先计算模7。
时间复杂性:
预先计算O(N)
总体O(Q) + O(N)
2:分而治之的方法
它是一个segment tree解决方案。
在每个树节点上,您将mod 7存储为该节点中数字形成的数字
并且第一种方法中给出的表达式可以用于通过组合两个孩子的mod 7值来找到父亲的mod 7
此解决方案的时间复杂度为O(Q log N) + O(N log N)
答案 2 :(得分:0)
首先为0开头的每个数字建立一个模数为7的数字列表(如你的情况,0%7,3%7,35%7,357%7 ...)然后为每个情况( a,b)抓取数字[a-1]和数字[b],然后将数字[b]乘以由(1+b-a)%6
定义的10 ^ X模7的1-3-2-6-4-5序列,相比。如果这些相等,则返回YES,否则返回NO。伪代码:
readString(big);
Array a=[0]; // initial value
Array tens=[1,3,2,6,4,5]; // quick multiplier lookup table
int d=0;
int l=big.length;
for (int i=0;i<l;i++) {
int c=((int)big[i])-48; // '0' -> 0, and "big" has characters
d=(3*d+c)%7;
a.push(d); // add to tail
}
readInt(q);
for (i=0;i<q;i++) {
readInt(li);
readInt(ri); // get question
int left=(a[li-1]*tens[(1+ri-li)%6])%7;
if (left==a[ri]) print("YES"); else print("NO");
}
测试示例:
247761901
1
5 9
61901%7 = 0。计算:
a = [0 2 3 2 6 3 3 4 5 2]
li = 5
ri = 9
left=(a[5-1]*tens[(1+9-5)%6])%7 = (6*5)%7 = 30%7 = 2
a[ri]=2
Answer: YES