Codeforces 1270G Subset with Zero Sum
Codeforces 1270G Subset with Zero Sum
https://codeforces.com/contest/1270/problem/G
长度为 \(n\) 的正整数序列 \(a_1,a_2,\cdots,a_n\) , 满足
\[i - n \le a_i \le i - 1
\]
请找出一个非空子序列满足和为 \(0\) .
可以证明总是存在合法方案.
有 \(T\) 组数据.
\(1 \le T \le 10^6\)
\(1 \le n \le 10^6, \sum n \le 10^6\)
Tutorial
将不等式变形
\[1 \le i -a_i \le n
\]
可以建立一张 \(n\) 个点的有向图,从 \(i\) 向 \(i-a_i\) 连边.
那么图中一定存在一个有向环,找到任意一个这样的环,设其中的点为 \(u_1,u_2,\cdots,u_k\) ,则有
\[u_1-a_{u_1}=u_2 \\
u_2-a_{u_2}=u_3 \\
\cdots \\
u_k-a_{u_k}=u_1
\]
所以可以得到 \(a_{u_1}+a_{u_2}+\cdots+a_{u_k}=0\) .
复杂度 \(O(n)\)
Code
#include <cassert>
#include <cstdio>
#include <iostream>
#include <vector>
#define debug(...) fprintf(stderr,__VA_ARGS__)
using namespace std;
inline char nc()
{
// return getchar();
static char buf[100000],*l=buf,*r=buf;
return l==r&&(r=(l=buf)+fread(buf,1,100000,stdin),l==r)?EOF:*l++;
}
template<class T> void read(T &x)
{
x=0; int f=1,ch=nc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=nc();}
while(ch>='0'&&ch<='9'){x=x*10-'0'+ch;ch=nc();}
x*=f;
}
typedef long long ll;
const int maxn=1e6+50;
int n;
int T;
int a[maxn];
bool vis[maxn];
vector<int> R;
vector<int> an;
void dfs(int u)
{
if(vis[u]) return; vis[u]=1;
R.push_back(u);
dfs(u-a[u]);
}
int main()
{
read(T);
for(int kase=1;kase<=T;++kase)
{
read(n);
for(int i=1;i<=n;++i)
{
read(a[i]);
}
dfs(1);
ll sum=0;
for(int i=R.size()-1;~i;--i)
{
sum+=a[R[i]]; an.push_back(R[i]);
if(sum==0) break;
}
printf("%d\n",(int)an.size());
for(int i=0;i<an.size();++i)
{
if(i) printf(" ");
printf("%d",an[i]);
}
printf("\n");
R.clear();
an.clear();
for(int i=1;i<=n;++i) vis[i]=0;
}
return 0;
}