PTA 开军舰前の体能训练(简单数论+模拟)

书接上回,四年级学生选出了有资格开军舰的一年级学生后,自然要对他们进行体能训练了hhhhhhhh

训练是在一片无限大的操场上进行的,操场是一片长与宽无限大的正方形,而操场又可以分成若干个长度为单位长度的正方形。这些正方形上都标有序号,标号方式如下图示:

而一年级学生且按照如下的规则移动:

  • 如果第i秒在标号为x的格子处,则第i+1秒在标号为i+1的格子处。

  • 第一秒的时候一年级的学生在标号为1的格子处。

经过很久很久以后,四年级学生已经找不到这些学生的方位了。现在请聪明的你来帮他们查询一下吧。

他们想知道:经过t秒后,一年级学生在何处和已经知道一年级学生在第r行和第c列时,距离开始已经过了多少秒了。

输入格式:

输入文件的第一行将给出一个数t(1≤t≤105),为聪明的你要处理的查询数。

输入文件的第二行开始直到第t+1行将按如下格式读入查询:

  • 1 x y:表示查询的学生此时位于第x行第y列(1≤x,y≤108)

  • 2 t:表示查询的学生此时恰好在第t秒时(1≤t≤1016)

    输出格式:

针对输入文件,你的输出应该有t行。其中第i(1≤i≤t)为针对第i条查询的回答。即:

如果你的查询为1 x y,则你应该回答当一年级学生在第x行第y列时的时刻,输出一个数t即可。

如果你的查询为2 t,则你应该回答在t秒时一年级学生应该在第几行第几列。应输出两个数x y,代表在第x行第y列。

样例1

样例输入

5
1 1 1
1 1 2
1 1 3
1 2 1
1 2 2

样例输出

1
2
9
4
3

思路:观察表可知,行开头和列开头是和i,j有关的,所以可以直接求

吐槽:这题样例是真抽象,必须全写对才给一半分,剩下另一半是longlong 、

AC代码:

2024/04/10更新代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
//待到秋来九月八,我花开后百花杀
signed main(){
    int t;cin>>t;
    while(t--){
        int op;cin>>op;
        if(op==1){
            int x,y;cin>>x>>y;
            int st = 0;
            if(x<=y){
                if(y%2==0) st = (y-1)*(y-1) + x;
                else st = y*y - (x-1);
            }else{
                if(x%2==0)st = x*x - (y-1);
                else st =(x-1)*(x-1) + y;
            }
            cout<<st<<endl;
        }else{
            int now;cin>>now;
            int x,y;
            int mid = sqrt(now);
            if(mid * mid == now){
                if(mid % 2 == 0)x = mid,y = 1;
                else x = 1, y = mid;
            }else{
                mid+=1;//向上取整,是的 mid*mid >= now;
                if(now > (mid * mid) - (mid - 1)){
                    if(mid % 2 ==0 )x = mid, y = mid * mid + 1 - now;
                    else x = mid * mid + 1 - now, y = mid;
                }else{
                    if(mid % 2 == 0)y = mid, x = now - (mid - 1) * (mid - 1) ;
                    else y = now - (mid - 1) * (mid - 1), x = mid;
                }
            }
            cout<<x<<" "<<y<<endl;
        }
    }

    return 0;
}

之前的写,有点臭 

#include<bits/stdc++.h>
using namespace std;

int main(){
	int t;
	cin>>t;
	while(t--){
		long long a,b,c;
		long long ans;
		cin>>c;
		if(c==1){
			cin>>a>>b;
			if(a<b){
				long long lie;
				if(b%2!=0){
					lie = b*b;
					ans = lie - a+1;
				}else{
					lie = (b-1)*(b-1);
					lie+=1;
					ans  =lie +a-1;
				}
				
				cout<<ans<<endl;
			}else if(a==b){
				ans = a*a-(a-1);
				cout<<ans<<endl;
			}else{
				long long hang;
				if(a==1){
					hang  =1;
				}else if(a%2==0){
					
					hang =a*a;
					ans = hang -b+1;

				}else{
					hang = (a-1)*(a-1);
					hang+=1;
					
					ans = hang +b-1;
				}
				cout<<ans<<endl;
				
			}	
		}else{
			long long aa;
			cin>>aa;
			long long x,y;
			long long q = sqrt(aa);
			if((q*q)==aa){
				if(q%2==0){
					cout<<q<<" "<<1<<endl;
				}else{
					cout<<1<<" "<<q<<endl;
				}
			}else{
				q++;
				long long x,y;
				
				long long xc = (q*q)-aa;
				
				if(aa>(q*q-(q-1))){
					if(q%2==0){
					 	x = q;
					 	y = q*q+1 - aa;
					 	cout<<x<<" "<<y<<endl;
					}else{
						x = q;
					 	y = q*q+1 - aa;
					 	cout<<y<<" "<<x<<endl;
					}
					
				}else{
					if(q%2==0){
					 	x = q;
					 	y = aa - (q-1)*(q-1);
					 	cout<<y<<" "<<x<<endl;
					}else{
						x = q;
					 	y = aa - (q-1)*(q-1);
					 	cout<<x<<" "<<y<<endl;
					}
				}
				
	
				
			}
			
			
		}
	}
	return 0;
	
} 	

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值