LG9154

很显然地,除了 \(3^0\) 只能选一次外,每个 \(3\) 的幂最多可以用两次。于是我们可以类比二进制拆分的思路,依次枚举 \(3\) 的幂,每次找到小于当前数的最大的幂并减去,统计次数,发现非 \(0\) 次幂出现次数大于 \(2\)\(0\) 次幂大于 \(1\) 时则输出 \(0\),否则运用乘法原理计数。

本人在赛时发现了一个规律:对于任意的 \(a \equiv0 \pmod3\),都有 \(ans_a = ans_{a+1}\)。因此可以直接转换后计算。

代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define int unsigned long long

using namespace std;

int inv[38];
int pd[38];
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
	return x*f;
}

signed main()
{
	
	int T,ans,k;
	int n;
	inv[0] = 1;
	for( int i = 1 ; i <= 37 ; i ++ )
		inv[i] = inv[i - 1] * 3;
	cin >> T;
	while( T -- )
	{
		k = 0;
		memset( pd , 0 , sizeof(pd) );
		ans = 0;
		n = read(); 
		if( n % 3 == 0 ) n ++,k = 1;
		while( n > 0 )
		{
			int i;
			for( i = 0 ; i <= 37 ; i ++ )
			{
				if( inv[i] > n )
					break;
			}
			if( pd[i - 1] == 2 )
			{
				ans = 0;
				break;
			} 
			pd[i - 1] ++ ;
			n -= inv[i - 1];
			ans ++;
		}
		if( ans == 0 ||( pd[0] > 1 && !k)) cout << 0 << endl;
		else 
		{
			ans = 1;
			for( int i = 1 ; i <= 37 ; i ++ )
				if( pd[i] == 1 )
					ans = ans * 2;
			cout << ans << endl;
		}
	}
	return 0;
}
posted @ 2024-01-20 18:02  liyilang2021  阅读(2)  评论(0编辑  收藏  举报