题目
有n个地方 每个地方的唱歌时间固定值为bi
每个地方都有一个歌手ai,他在这个地方唱完后会去(i+1)mod n 的地方,并且时间加倍,也就是 ai 2ai 3ai …nai 。
他会走完所有地方。
求是否存在一个ai数组使得所有bi都成立。
题解思路
这种数列的部分和的题,第一步肯定是错位减减找性质。
可以得到 sum(a[i]) - na[i] = 差值
而sum其实是可以之前求出来的
每个歌手都唱了ai 2ai … nai
求和就是 (1 + 2 … n) sum(a[i]) == sum(b[i) 。
然后在每一步判断值的合法性即可。
枚举a[i]的二分
自己写了个二分居然过了,实际上不需要二分的。
这个二分还爆了longlong 开了int128才过的。
AC代码
正常解法
#include <bits/stdc++.h>
//#include <unordered_map>
//priority_queue
#define PII pair<int,int>
#define ll long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 200100;
int n ;
long long a[N] ;
long long sum , st , s ;
int main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int T ;
cin >> T ;
while ( T-- )
{
s = sum = st = 0 ;
cin >> n ;
for (int i = 1 ; i <= n ; i++ )
cin >> a[i] , sum += a[i] , st += i ;
if ( n == 1 )
{
cout << "YES\n" ;
cout << a[1] << "\n" ;
}else
{
if ( sum % st )
{
cout << "NO\n" ;
}else
{
s = sum/st ;
int falg = 1 ;
vector <int> ans ;
for (int i = 1 ; i <= n ; i++ )
{
long long sp ;
if ( i == 1 )
sp = a[1] - a[n] ;
else
sp = a[i] - a[i-1] ;
if ((s - sp)%n || (s-sp)/n < 1 || (s-sp)/n > 1e9 )
falg = 0 ;
ans.push_back((s-sp)/n) ;
}
if (falg)
{
cout << "YES\n" ;
for ( auto i : ans )
cout << i << " " ;
cout << "\n" ;
}else
cout << "NO\n" ;
}
}
}
return 0 ;
}
二分解法
#include <bits/stdc++.h>
//#include <unordered_map>
//priority_queue
#define PII pair<int,int>
#define ll long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 200100;
long long a[N] ;
long long sum ;
long long st ;
long long dt ;
int n ;
bool che(long long p )
{
long long sm = n*p + dt ;
if ( (__int128)st*sm >= sum )
return 1 ;
else
return 0 ;
}
int main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int T ;
cin >> T ;
while ( T-- )
{
sum = st = 0 ;
cin >> n ;
for (int i = 1 ; i <= n ; i++ )
cin >> a[i] , sum += a[i] , st += i ;
if ( n == 1 )
{
cout << "YES\n" ;
cout << a[1] << "\n" ;
}else
{
long long t1 = 1 , t2 = 1e9 + 7 ;
dt = a[1] - a[n] ;
while ( t1 < t2 )
{
long long mid = t1 + t2 >> 1 ;
if (che(mid))
{
t2 = mid ;
}else
t1 = mid + 1 ;
}
if ( st*(n*t2 + dt) == sum )
{
int falg = 1 ;
vector <int> ans ;
if ( t2 < 1 || t2 > 1e9 )
falg = 0 ;
ans.push_back(t2) ;
long long sk = n*t2 + dt ;
for (int i = 2 ; i <= n ; i++ )
{
long long ff = ( sk - (a[i] - a[i-1] )) ;
if ( ff % n )
falg = 0 ;
if ( ff/n < 1 || ff/n > 1e9 )
falg = 0 ;
ans.push_back(( sk - (a[i] - a[i-1] ))/n) ;
}
if ( falg )
{
cout << "YES\n" ;
for ( auto i : ans )
cout << i << " ";
cout << "\n" ;
}else
cout << "NO\n" ;
}else
{
cout << "NO\n" ;
}
}
}
return 0 ;
}