Codeforces Global Round 10 E Omkar and Duck

Omkar and Duck

题目链接

题目大意

这是一个交互题,
你先给出一个矩阵,然后输入权值,这个权值是矩阵中(1,1)点到(n,n)点的路径上的权值和。让你输出这个路径。
所以要保证每种走法的路径权值和都不一样。

题解

做的时候想到了,可能的权值是0~x (x是走法的数量)。
但是不会构造,,画了好多,没构造出来。。

其实只要让x步后所能到达每个点的权值范围都不一样即可。
x步能到达的点就是左下到右上对角线上的点。,
所以只要让从1,1点到每个对角线上的每个点的权值范围不同即可。
这样的话,就可以一个斜线一个斜线看,
在每一个斜线上当前的范围得从上一个的范围+1开始。
代码:

#include
#include
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<double,double> pdd;
typedef unsigned long long ull;
typedef unordered_set<int>::iterator sit;
#define st first
#define sd second
#define mkp make_pair
#define pb push_back
void tempwj(){freopen("hash.in","r",stdin);freopen("hash.out","w",stdout);}
ll gcd(ll a,ll b){return b == 0 ? a : gcd(b,a % b);}
ll qpow(ll a,ll b,ll mod){a %= mod;ll ans = 1;while(b > 0){if(b & 1)ans = ans * a % mod;a = a * a % mod;b >>= 1;}return ans;}
struct cmp{bool operator()(const pii & a, const pii & b){return a.second > b.second;}};
int lb(int x){return  x & -x;}
//friend bool operator < (Node a,Node b)   重载
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll mod = 998244353;
const int maxn = 2e5+10;
const int M = 1e6 + 2;
ll a[30][30];
pll pp[30][30];
int main()
{
	int n;
	scanf("%d",&n);
	pp[1][1] = mkp(0,0);
	for (int i = 3; i <= 2 * n; i ++ )
	{
		ll per = 0;
		for(int j = 1; j <= n; j ++ )
		{
			for (int k = 1; k <= n; k ++ )
			{
				if(j + k != i)
					continue;
				ll maxx = 0, minn = INF;
				if(j - 1 >= 1)
				{
					maxx = max(maxx,pp[j - 1][k].sd);
					minn = min(minn,pp[j - 1][k].st);
				}
				if(k - 1 >= 1)
				{
					maxx = max(maxx,pp[j][k - 1].sd);
					minn = min(minn,pp[j][k - 1].st);
				}
				pp[j][k] = mkp(per, per + maxx - minn);
				a[j][k] = per - minn;
				per = pp[j][k].sd + 1;
				
			}
		}
	}
	for (int i =1; i <= n; i ++ )
	{
		for (int j = 1; j <= n; j ++ )
			printf("%lld ",a[i][j]);
		printf("\n");
		fflush(stdout);
	}
	// for (int  i= 1; i <= n; i ++ )
	// {
	// 	for (int j = 1; j <= n; j ++ )
	// 	{
	// 		printf("%lld %lld   ",pp[i][j].st,pp[i][j].sd);
	// 	}
	// 	printf("\n");
	// }
	int q;
	scanf("%d",&q);
	std::vector<pii> vv;
	while(q -- )
	{
		vv.clear();
		ll s;
		scanf("%lld",&s);
		int x = n, y = n; 
		s -= a[n][n];
		vv.pb(mkp(n,n));
		while(x > 1 || y > 1)
		{
			if(x > 1 && s >= pp[x - 1][y].st && s <= pp[x - 1][y].sd)
			{
				s -= a[x - 1][y];
				vv.pb(mkp(x - 1,y));
				x -- ;
			}
			else
			{
				s -= a[x][y - 1];
				vv.pb(mkp(x, y - 1));
				y -- ;
			}
		}
		for (int  i= vv.size() - 1; i >= 0; i -- )
		{
			printf("%d %d\n",vv[i].st,vv[i].sd);
			fflush(stdout);
		}
	}
	
}

你可能感兴趣的:(做题笔记)