Codeforces Round #760 (Div. 3)
比赛链接
Codeforces Round #760 (Div. 3)
E. Singers' Tour
\(n\) towns are arranged in a circle sequentially. The towns are numbered from 1 to \(n\) in clockwise order. In the \(i\)-th town, there lives a singer with a repertoire of \(a_{i}\) minutes for each \(i \in[1, n]\).
Each singer visited all \(n\) towns in clockwise order, starting with the town he lives in, and gave exactly one concert in each town. In addition, in each town, the \(i\)-th singer got inspired and came up with a song that lasts \(a_{i}\) minutes. The song was added to his repertoire so that he could perform it in the rest of the cities.
Hence, for the \(i\)-th singer, the concert in the \(i\)-th town will last \(a_{i}\) minutes, in the \((i+1)\)-th town the concert will last \(2 \cdot a_{i}\) minutes, ..., in the \(((i+k) \bmod n+1)\)-th town the duration of the concert will be \((k+2) \cdot a_{i}, \ldots\), in the town \(((i+n-2) \bmod n+1)-n \cdot a_{i}\) minutes.
You are given an array of \(b\) integer numbers, where \(b_{i}\) is the total duration of concerts in the \(i\)-th town. Reconstruct any correct sequence of positive integers \(a\) or say that it is impossible.
Input
The first line contains one integer \(t\left(1 \leq t \leq 10^{3}\right)\) - the number of test cases. Then the test cases follow.
Each test case consists of two lines. The first line contains a single integer \(n\left(1 \leq n \leq 4 \cdot 10^{4}\right)-\) the number of cities. The second line contains \(n\) integers \(b_{1}, b_{2}, \ldots, b_{n}\left(1 \leq b_{i} \leq 10^{9}\right)\) - the total duration of concerts in \(i\)-th city.
The sum of \(n\) over all test cases does not exceed \(2 \cdot 10^{5}\).
Output
For each test case, print the answer as follows:
If there is no suitable sequence \(a\), print NO. Otherwise, on the first line print YES, on the next line print the sequence \(a_{1}, a_{2}, \ldots, a_{n}\) of \(n\) integers, where \(a_{i}\left(1 \leq a_{i} \leq 10^{9}\right)\) is the initial duration of repertoire of the \(i\)-th singer. If there are multiple answers, print any of them.
Example
input
4
3
12 16 14
1
1
3
1 2 3
6
81 75 75 93 93 87
output
YES
3 1 3
YES
1
NO
YES
5 5 4 1 4 5
Note
Let's consider the 1-st test case of the example:
- the 1-st singer in the 1-st city will give a concert for 3 minutes, in the 2 -nd - for 6 minutes, in the 3 -rd - for 9 minutes;
- the 2 -nd singer in the 1 -st city will give a concert for 3 minutes, in the 2 -nd - for 1 minute, in the 3 -rd - for 2 minutes;
- the 3 -rd singer in the 1 -st city will give a concert for 6 minutes, in the 2 -nd - for 9 minutes, in the 3 -rd - for 3 minutes.
解题思路
构造,线性代数
即求解如下 \(n\) 个 \(n\) 元一次方程组:
\(
\begin{cases}
& a_1+ n\times a_2+(n-1)\times a_3+\dots +2\times a_n=b_1 \\
& 2\times a_1+a_2+n\times a_3+\dots +3\times a_n=b_2 \\
& \vdots \\
& n\times a_1 + (n-1)\times a_2 +(n-2)\times a_3+\dots +a_n=b_n
\end{cases}
\)
当高斯消元的复杂度为 \(n^3\),会超时,不妨先从小点的范围开始构造
构造答案前,将上面的等式加起来,有 \(\frac{(n+1)\times n}{2} \times \sum_{i=1}^n a_i=\sum_{i=1}^n b_i\),则必须有 \(\sum_{i=1}^n b_i \%\frac{(n+1)\times n}{2} =0\)
从 \(n=3\) 开始构造:
有如下等式:
\(
\begin{cases}
& a_1+2a_2+2a_3=b_1 \\
& 2a_1+a_2+3a_3=b_2 \\
\end{cases}
\)
做差,得 \(
-a_1+2a_2-a_3=b_1-b_2
\),即 \(a_2=\frac{b_1-b_2+a_1+a_2+a_3}{3}\),
得构造得到解:\(a[i\%n+1]=\frac{b[i]-b[i\%n+1]+\sum_{i=1}^na[i]}{n}\),注意 \(a[i]\) 为正整数,且范围为 \([1,10^9]\)
- 时间复杂度:\(O(n)\)
代码
// Problem: E. Singers' Tour
// Contest: Codeforces - Codeforces Round #760 (Div. 3)
// URL: https://codeforces.com/contest/1618/problem/E
// Memory Limit: 256 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
// %%%Skyqwq
#include <bits/stdc++.h>
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
template <typename T> void inline read(T &x) {
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}
const int N=4e4+5;
int n,t;
LL a[N],b[N];
int main()
{
for(scanf("%d",&t);t;t--)
{
scanf("%d",&n);
LL sum=0;
for(int i=1;i<=n;i++)scanf("%lld",&b[i]),sum+=b[i];
int all=1ll*n*(n+1)/2;
if(sum%all!=0)
{
puts("NO");
continue;
}
sum/=all;
bool f=true;
for(int i=1;i<=n;i++)
{
LL t=b[i]-b[i%n+1]+sum;
if(t%n!=0)
{
f=false;
break;
}
a[i%n+1]=t/n;
if(!(a[i%n+1]>=1&&a[i%n+1]<=1e9))
{
f=false;
break;
}
}
if(!f)puts("NO");
else
{
puts("YES");
for(int i=1;i<=n;i++)printf("%lld ",a[i]);
puts("");
}
}
return 0;
}
F. Reverse
You are given two positive integers \(x\) and \(y\). You can perform the following operation with \(x\) : write it in its binary form without leading zeros, add 0 or 1 to the right of it, reverse the binary form and turn it into a decimal number which is assigned as the new value of \(x\).
For example:
- \(34\) can be turned into \(81\) via one operation: the binary form of \(34\) is \(100010\) , if you add \(1\) , reverse it and remove leading zeros, you will get \(1010001\) , which is the binary form of \(81\) .
- \(34\) can be turned into \(17\) via one operation: the binary form of \(34\) is $100010 $, if you add \(0\) , reverse it and remove leading zeros, you will get \(10001\) , which is the binary form of \(17\) .
- \(81\) can be turned into \(69\) via one operation: the binary form of \(81\) is \(1010001\) , if you add \(0\) , reverse it and remove leading zeros, you will get \(1000101\) , which is the binary form of \(69\) .
- \(34\) can be turned into \(69\) via two operations: first you turn \(34\) into \(81\) and then \(81\) into \(69\) .
Your task is to find out whether \(x\) can be turned into \(y\) after a certain number of operations (possibly zero).
Input
The only line of the input contains two integers \(x\) and \(y\left(1 \leq x, y \leq 10^{18}\right)\).
Output
Print YES
if you can make \(x\) equal to \(y\) and NO
if you can't.
解题思路
dfs,记忆化搜索
对于一个数二进制,如果其后面没有 \(0\),则如果在其后面加 \(0\) 的话翻转后前导 \(0\) 会去掉,相当于翻转原二进制串,即后面只能加 \(1\),这就相当于只能在原二进制串前后加 \(1\),且可翻转;如果一个数的二进制后面有 \(0\),则有两种选择:将后面的 \(0\) 去掉,在后面加 \(1\),这时两遍 \(dfs\) 即可
- 时间复杂度:\(O(32\times 32)\)
代码
// Problem: F. Reverse
// Contest: Codeforces - Codeforces Round #760 (Div. 3)
// URL: https://codeforces.com/contest/1618/problem/F
// Memory Limit: 256 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
// %%%Skyqwq
#include <bits/stdc++.h>
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
template <typename T> void inline read(T &x) {
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}
LL x,y;
unordered_set<string> s;
string get(LL x)
{
string res;
do
{
res+='0'+(x&1);
x>>=1;
}while(x);
return res;
}
void dfs(string x)
{
if(s.count(x)||x.size()>=64)return ;
s.insert(x);
reverse(x.begin(),x.end());
dfs(x);
x+='1';
dfs(x);
x.pop_back();
x='1'+x;
dfs(x);
}
int main()
{
cin>>x>>y;
string st=get(x),en=get(y);
reverse(st.begin(),st.end());
reverse(en.begin(),en.end());
if(st.back()=='0')
{
s.insert(st);
dfs(st+'1');
while(st.size()&&st.back()=='0')st.pop_back();
dfs(st);
}
else
dfs(st);
puts(s.count(en)?"YES":"NO");
return 0;
}