E. Singers‘ Tour(数学推导)

Problem - 1618E - Codeforces
 

将n个城镇按顺序排列成一个环。这些城镇按顺时针顺序编号为1到n。在第i个城镇里,有一名歌手,他的曲目列表中每首歌的演唱时间为ai分钟,其中i∈[1,n]。

每位歌手按顺时针顺序访问所有n个城镇,并在每个城镇举办一场音乐会。另外,在每个城镇中,第i位歌手受到灵感,创作了一首时长为ai分钟的歌曲。这首歌被加入到他的曲目列表中,以便他可以在余下的城镇中演唱它。

因此,对于第i位歌手,他在第i个城镇的音乐会持续ai分钟,在(i+1)个城镇的音乐会持续2⋅ai分钟,...,在((i+k)modn+1)个城镇中音乐会的持续时间为(k+2)⋅ai分钟,...,在第((i+n−2)modn+1)个城镇中音乐会的持续时间为n⋅ai分钟。

给定一个由b个整数组成的数组,其中bi是第i个城镇中音乐会的总持续时间。重构任何正确的正整数序列a或者说明不可能重构。 输入

第一行包含一个整数t(1≤t≤103),表示测试用例的数量。然后是测试用例。

每个测试用例由两行组成。第一行包含一个整数n(1≤n≤4⋅104),表示城市的数量。第二行包含n个整数b1,b2,…,bn(1≤bi≤109),表示第i个城市音乐会的总持续时间。

所有测试用例中n的总和不超过2⋅105。 输出

对于每个测试用例,按以下方式输出答案:

如果没有合适的序列a,打印NO。否则,第一行打印YES,在接下来的一行打印n个整数a1,a2,…,an,其中ai(1≤ai≤109)是第i个歌手曲目的初始持续时间。如果有多个答案,可以打印任意一个。

Example

Input

Copy

4
3
12 16 14
1
1
3
1 2 3
6
81 75 75 93 93 87

Output

Copy

YES
3 1 3 
YES
1 
NO
YES
5 5 4 1 4 5 

注意

让我们考虑示例中的第一个测试用例:

第1位歌手在第1个城市举办了一场为3分钟的音乐会,在第2个城市为6分钟,在第3个城市为9分钟;

第2位歌手在第1个城市举办了一场为3分钟的音乐会,在第2个城市为1分钟,在第3个城市为2分钟; 第3位歌手在第1个城市举办了一场为6分钟的音乐会,在第2个城市为9分钟,在第3个城市为3分钟。

题解:

我们假设每一位的初始值是

a1,a2,a3...an,由于每个歌手都会成一个环

都会演唱(n + 1)*n/2*a[i],这么长时间,而所有歌手的相加和就是sum = b1 + ....bn

那么m = a1 +... an = sum/[(n + 1)*n/2]

假设n = 3

b1 = a1 + 3*a2 + 2*a3

b2 = 2*a1 + a2 + 3*a3

b2 - b1 = a1 - 2*a2 + a3

b2 - b1 + 3*a2 = a1 + a2 + a3

3*a2 = b1 - b2 + a1 + a2 + a3

a2 = (b1 - b2 + m)/n

接着计算答案即可,中间注意限制条件

#include <cstdio>
#include <cstring>
#include <algorithm>
#include<iostream>
#include<vector>
#include<set>
#include<map>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
 #define int long long
typedef pair<int,int> PII;
typedef unsigned long long ULL;
const int N = 5e5 + 10;
int mod = 998244353;
int b[N];
void solve()
{
	int n;
	cin >> n;
	vector<int> ans(n + 10);
	int m = n*(n + 1)/2,s = 0;
	for(int i = 1;i <= n;i++)
	{
		int x;
		cin >> x;
		b[i] = x;
		s += x;
	}
	if(s%m ||s/m < n)
	{
		cout <<"NO\n";
		return ;
	}
	m = s/m;
	for(int i = 1;i <= n;i++)
	{
		ans[i%n + 1] = (b[i] - b[i%n + 1] + m)/n;
		if((b[i] - b[i%n + 1] + m)%n || ans[i%n + 1] > 1e9||ans[i%n + 1] < 1)
		{
			cout <<"NO\n";
			return;
		}
	}
	cout <<"YES\n";
	for(int i = 1;i <= n;i++)
	{
		cout << ans[i] <<" ";
	}
	cout <<"\n";
}
signed main()
{
	ios::sync_with_stdio(0 );
	cin.tie(0);cout.tie(0);
	int t = 1;
	cin >> t;
	while(t--)
	{
		solve(); 
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
/* * 程序名称:歌手比赛系统 * 程序作者:XXX * 编写时间:20XX年XX月XX日 * 版权声明:本程序版权归作者所有,仅供学习交流使用,禁止商业化利用。 */ #include <stdio.h> #include <stdlib.h> #include <string.h> /* 定义常量 */ #define MAX_SINGER 100 // 参赛歌手最大数量 #define MAX_NAME_LENGTH 20 // 歌手姓名最大长度 /* 定义结构体 */ struct Singer { char name[MAX_NAME_LENGTH]; // 歌手姓名 int score; // 歌手得分 }; /* 函数声明 */ void menu(); // 显示菜单 void addSinger(struct Singer singers[], int *count); // 添加歌手 void showSingers(struct Singer singers[], int count); // 显示所有歌手信息 void vote(struct Singer singers[], int count); // 投票 void sortSingers(struct Singer singers[], int count); // 根据得分排序歌手 /* 主函数 */ int main() { struct Singer singers[MAX_SINGER]; // 参赛歌手数组 int count = 0; // 参赛歌手数量 while (1) { menu(); // 显示菜单 int choice; scanf("%d", &choice); switch (choice) { case 1: addSinger(singers, &count); break; case 2: showSingers(singers, count); break; case 3: vote(singers, count); break; case 4: sortSingers(singers, count); break; case 5: exit(0); default: printf("无效的选项,请重新输入\n"); break; } } return 0; } /* 显示菜单 */ void menu() { printf("**********欢迎来到歌手比赛系统**********\n"); printf("1.添加歌手\n"); printf("2.显示所有歌手信息\n"); printf("3.投票\n"); printf("4.根据得分排序歌手\n"); printf("5.退出系统\n"); printf("请输入选项:"); } /* 添加歌手 */ void addSinger(struct Singer singers[], int *count) { if (*count >= MAX_SINGER) { printf("已达到最大参赛人数!\n"); return; } struct Singer newSinger; printf("请输入歌手姓名:"); scanf("%s", newSinger.name); newSinger.score = 0; singers[*count] = newSinger; *count += 1; printf("添加成功!\n"); } /* 显示所有歌手信息 */ void showSingers(struct Singer singers[], int count) { printf("所有参赛歌手信息如下:\n"); for (int i = 0; i < count; i++) { printf("姓名:%s,得分:%d\n", singers[i].name, singers[i].score); } } /* 投票 */ void vote(struct Singer singers[], int count) { printf("请输入您要投票的歌手姓名:"); char name[MAX_NAME_LENGTH]; scanf("%s", name); for (int i = 0; i < count; i++) { if (strcmp(singers[i].name, name) == 0) { singers[i].score += 1; printf("投票成功!\n"); return; } } printf("未找到该歌手,请重新输入\n"); } /* 根据得分排序歌手 */ void sortSingers(struct Singer singers[], int count) { for (int i = 0; i < count - 1; i++) { for (int j = 0; j < count - i - 1; j++) { if (singers[j].score < singers[j + 1].score) { struct Singer temp = singers[j]; singers[j] = singers[j + 1]; singers[j + 1] = temp; } } } printf("根据得分排序后的歌手信息如下:\n"); for (int i = 0; i < count; i++) { printf("姓名:%s,得分:%d\n", singers[i].name, singers[i].score); } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值