NOIP2017初赛阅读程序写结果第4题题解
一、题面
#include<iostream>
using namespace std;
int main()
{
int n, m;
cin >> n >> m;
int x = 1;
int y = 1;
int dx = 1;
int dy = 1;
int cnt = 0;
while (cnt != 2)
{
cnt = 0;
x = x + dx;
y = y + dy;
if (x == 1 || x == n)
{
++cnt;
dx = -dx;
}
if (y == 1 || y == m)
{
++cnt;
dy = -dy;
}
}
cout << x << " " << y << endl;
return 0;
}
输入 1:4 3
输出 1:_________
输入 2:2017 1014
输出 2:_________
二、前置约定
1.我们称一次
cnt = 0;
x = x + dx;
y = y + dy;
if (x == 1 || x == n)
{
++cnt;
dx = -dx;
}
if (y == 1 || y == m)
{
++cnt;
dy = -dy;
}
为一步。
2.我们称x==1∣∣x==n∣∣y==1∣∣y==mx==1||x==n||y==1||y==mx==1∣∣x==n∣∣y==1∣∣y==m为到边缘。
三、解法
可以发现每一步(x+y)(x+y)(x+y)都有三种情况的变化:+2,-2,不变。所以每一步(x+y)(x+y)(x+y)奇偶性不变。而最开始1+1是偶数,所以最后(x+y)(x+y)(x+y)也是偶数。
显然最后不会是n=1且m=1,因为在这之前程序就会结束。
考虑n,m的奇偶性
第一种情况:两个都是偶数 。则(1+n)(1+n)(1+n),(1+m)(1+m)(1+m)都是奇数。最后x=n,y=m。
第二种情况:n是偶数,m是奇数。则(1+n)(1+n)(1+n),(n+m)(n+m)(n+m)都是奇数,最后x=1,y=m。
第三种情况:n是奇数,m是偶数。与第二种情况类似。最后x=n,y=1。
那么问题来了,当n和m都是奇数的时候答案是什么呢?
因为x,y奇偶性相同,m每次到边缘x,y都是奇数。所以从某一次到边缘到下一次到边缘必经过偶数步。又每一步(x+y)(x+y)(x+y)变化偶数,所以(x+y)(x+y)(x+y)除以4的余数始终不变,为1+1=2。
此时又分几种情况:
第一种情况:n=4p+3,m=4q+3。则(n+1)(n+1)(n+1),(m+1)(m+1)(m+1)都是除以4余0的数。最后x=n,y=m。
第二种情况:n=4p+1,m=4q+3。则(n+m)(n+m)(n+m),(m+1)(m+1)(m+1)都是除以4余0的数。最后x=n,y=1。
第三种情况:n=4p+3,m=4q+1。则(n+m)(n+m)(n+m),(n+1)(n+1)(n+1)都是除以4余0的数。最后x=1,y=m。
那么问题来了,当n和m都是除以4余1的数的时候的答案是什么呢?
因为因为每次到边缘必有x=4u+1,y=4v+1。所以从某一次到边缘到下一次到边缘必经过4的倍数步。又每一步(x+y)(x+y)(x+y)变化偶数,所以(x+y)(x+y)(x+y)除以8的余数始终不变,为2。
像之前那样,再分4种情况讨论。。。
这种算法在最坏情况下时间复杂度是O(logn)O(logn)O(logn),期望时间复杂度为O(1),非常适合考场上笔算(毕竟这是初赛题,不过这题数据太水,是O(1)O(1)O(1)的)
四、标程
因为这是初赛题,我就不在此次粘O(logn)的程序了。
这篇博客详细解析了NOIP2017初赛阅读程序写结果第4题,讨论了在不同情况下变量x和y的奇偶性变化,并给出了每种情况的解题思路。通过分析,得出在最坏情况下,该算法的时间复杂度为O(logn),但期望时间复杂度为O(1),适合快速笔算解答。

402

被折叠的 条评论
为什么被折叠?



