Codeforces Round #730 (Div. 2) D. RPD and Rap Sheet (交互,从easy到hard)

easy

hard

题意

已知密码是 k k k进制数,在十进制下是 [ 0 , n − 1 ] [0,n-1] [0,n1]之间,你有至多 n n n次机会猜测这个数

设你猜的数字是 y y y,如果答案正确,系统会返回 1 1 1

如果答案错误,系统将返回 0 0 0,而且会修改密码为 z z z

x ⊕ z = y x\oplus z=y xz=y

其中 x x x是上一次的密码, z z z是新密码, y y y是你本轮猜测的数

异或操作,是把 x , z x,z x,z转化为 k k k进制,对应位做模 k k k意义下的加法运算

(你只需要给出当前的密码而不是初始密码!!!)


e a s y easy easy

此时 k = 2 k=2 k=2,那么 z = x ⊕ y z=x\oplus y z=xy

考虑枚举每个数为初始密码

比如我认为 i i i是初始密码,那么经过我之前的一系列操作,现在密码变成什么样了呢??

设我之前猜测的数是 y 1 , y 2 . . . y k y_1,y_2...y_k y1,y2...yk,那么现在密码就应该是 r e s = y 1 ⊕ y 2 . . . ⊕ y k ⊕ i res=y_1\oplus y_2...\oplus y_k \oplus i res=y1y2...yki

于是我们猜测当前密码是 r e s res res,如果初始密码真的是 i i i我们就应该猜对了

否则,我们确信初始密码并不是 i i i,令 y k + 1 = r e s y_{k+1}=res yk+1=res

我们再去假定初始密码是 i + 1 i+1 i+1…反复迭代,显然可以在 n n n次内得到解

#include <bits/stdc++.h>
using namespace std;
const int maxn = 3e5+10; 
int t,n,k;
int guess(int ans)
{
	cout << ans << endl;
	int flag; cin >> flag;
	return flag;
}
signed main()
{
	cin >> t;
	while( t-- )
	{
		cin >> n >> k;
		int res = 0;
		for(int i=0;i<n;i++)
		{
			if( guess(res^i) )	break;
			res ^= ( res^i );	
		}
	}
}

h a r d hard hard

k k k可能不是二进制了.

再看看密码生成的机制(时刻记住这里的异或是对应位相加再模 k k k)

x ⊕ z = y x\oplus z=y xz=y

我们把 x , y , z x,y,z x,y,z每一位都拆开了,设 z i z_i zi表示 k k k进制下低位起的第 i i i位上的数字

那么 z i = ( ( y i − x i ) % k + k ) % k z_i=((y_i-x_i)\%k+k)\%k zi=((yixi)%k+k)%k.为了方便

设初始密码为 p w d pwd pwd

考虑如果是第一次询问,询问数字为 f 1 f_1 f1,猜错答案后新密码变为

z 1 = ( f 1 − p w d ) % k z_1=(f_1-pwd)\%k z1=(f1pwd)%k

考虑如果是第二次询问,询问数字为 f 2 f_2 f2,猜错答案后新密码变为

z 2 = ( f 2 − z 1 ) % k = ( f 2 − f 1 + p w d ) % k z_2=(f_2-z_1)\%k=(f_2-f_1+pwd)\%k z2=(f2z1)%k=(f2f1+pwd)%k

同理第三次生成的新密码是

z 2 = ( f 3 − z 2 ) % k = ( f 3 − f 2 + f 1 − p w d ) % k z_2=(f_3-z_2)\%k=(f_3-f_2+f_1-pwd)\%k z2=(f3z2)%k=(f3f2+f1pwd)%k

以此类推…

首先我们可以假定 p w d pwd pwd来求 z z z,求 z z z不就照着上面的公式套嘛!!

有两种大同小异的套法

Ⅰ.按照奇偶性给每次猜测的数 f i f_i fi分类,然后看看是加 p w d pwd pwd还是减 p w d pwd pwd

Ⅱ.每次对之前维护的 f f f值取反,然后加上本次猜测的 f f f值,然后判断是加 p w d pwd pwd还是减 p w d pwd pwd

代码用的Ⅰ

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e7+10; 
const int mx = 30;
int t,n,k;
int zhi[mx][2],lin[mx],base[mx];
vector<int>vec;
void init()
{	
	for(int i=0;i<mx;i++)	lin[i] = zhi[i][0] = zhi[i][1] = 0;
	base[0] = 1;
	for(int i=1;1ll*base[i-1]*k<=maxn;i++)	base[i] = base[i-1]*k;
}
void fenjie(int x)
{
	vec.clear();
	if( x==0 ){ vec.push_back(0); return; }
	while( x!=0 )	vec.push_back( x%k ), x/=k;
}
int upd(int &x,int y){ x = ( (x+y)%k+k )%k; }
int guess(int ans)
{
	cout << ans << endl;
	int flag; cin >> flag;
	return flag;
}
signed main()
{
	cin >> t;
	while( t-- )
	{
		cin >> n >> k;
		init();
		for(int i=0;i<n;i++)
		{
			//假设初始是i,那么现在变成了什么样子呢??
			int w = i&1, ans = 0;
			for(int j=0;j<mx;j++)
			{
				lin[j] = 0;
				upd( lin[j],zhi[j][w^1] ), upd( lin[j],-zhi[j][w] );
			}
			fenjie( i );
			if( i&1 )
			{
				for(int j=0;j<vec.size();j++)	upd( lin[j],-vec[j] );
			}
			else
			{
				for(int j=0;j<vec.size();j++)	upd( lin[j],vec[j] );				
			}
			for(int i=0;i<mx;i++)	ans += lin[i]*base[i];
			
			if( guess(ans) )	break;
			fenjie( ans );
			for(int j=0;j<vec.size();j++)	upd( zhi[j][i&1],vec[j] );
		}
	}
}
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值