A:瞎搞,
B:先记录把每个负数处理成
−
1
-1
−1,正数处理成
+
1
+1
+1对答案的贡献。然后分类讨论一下
−
1
-1
−1出现次数的奇偶性,然后加上0的贡献。
C:简单构造。
由于相邻
n
n
n个数的和的差值绝对值
<
=
1
<=1
<=1,并且任意一个和差值都
<
=
1
<=1
<=1,那么先考虑:
由于:
{
S
1
=
a
1
+
a
2
+
.
.
.
+
a
n
S
2
=
a
2
+
a
3
+
.
.
.
+
a
n
+
1
.
.
.
S
n
=
a
n
+
a
n
+
1
+
.
.
.
+
a
2
n
\begin{cases} S_1 = a_1+a_2+...+a_{n}\\ S_2 = a_2+a_3+...+a_{n+1}\\ ...\\ S_n = a_n+a_{n+1}+...+a_{2n}\\ \end{cases}
⎩⎪⎪⎪⎨⎪⎪⎪⎧S1=a1+a2+...+anS2=a2+a3+...+an+1...Sn=an+an+1+...+a2n
因此上面这个方程相邻两项相减我们就可以得到:
{
∣
a
1
−
a
n
+
1
∣
<
=
1
∣
a
2
−
a
n
+
2
∣
<
=
1
.
.
.
∣
a
n
−
a
2
n
∣
<
=
1
\begin{cases} |a_1-a_{n+1}| <= 1\\ |a_2-a_{n+2}| <= 1\\ ...\\ |a_n-a_{2n}| <= 1\\ \end{cases}
⎩⎪⎪⎪⎨⎪⎪⎪⎧∣a1−an+1∣<=1∣a2−an+2∣<=1...∣an−a2n∣<=1
所以我们可以固定
a
1
a1
a1的位置,奇数位置按
1
,
3
,
5...
1,3,5...
1,3,5...构造,偶数位置按
2
n
,
2
n
−
2
,
2
n
−
4...
2n,2n-2,2n-4...
2n,2n−2,2n−4...构造,对应距离为
n
n
n的地方分别是加一和减一。
无解的情况用set判断最大最小值之差。
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<stdio.h>
#include<string.h>
#include<queue>
#include<cmath>
#include<map>
#include<set>
#include<vector>
using namespace std;
#define inf 0x3f3f3f3f
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define mem(a,b) memset(a,b,sizeof(a));
#define lowbit(x) x&-x;
#define debugint(name,x) printf("%s: %d\n",name,x);
#define debugstring(name,x) printf("%s: %s\n",name,x);
typedef long long ll;
typedef unsigned long long ull;
const double eps = 1e-6;
const int maxn = 1e5+5;
const int mod = 1e9+7;
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-'0';ch=getchar();}
return x*f;
}
int n;
int a[4*maxn];
int dp[4*maxn];
set<int>st;
int main() {
cin>>n;
int c1 = 1, c2 = n*2;
for(int i = 1; i <= n; i++){
if(i&1) {
a[i] = c1;
a[i+n] = c1+1;
c1 += 2;
}else{
a[i] = c2;
a[i+n] = c2-1;
c2 -= 2;
}
}
for(int i = 1; i <= 2*n; i++)
a[i+2*n] = a[i];
int sum = 0;
for(int i = 1; i <= n; i++){
dp[1] = dp[1] + a[i];
}
int cnt = 1;
st.insert(dp[1]);
int f = 0;
for(int i = 2; i <= 2*n; i++){
dp[i] = dp[i-1] - a[i-1] + a[i+n-1];
if(abs(*st.begin()-dp[i]) > 1){
f = 1;
break;
}
st.insert(dp[i]);
}
if(*st.rbegin()-*st.begin() > 1) f = 1;
if(f == 1) puts("NO");
else {
puts("YES");
for(int i = 1; i <= 2*n; i++)
printf("%d ",a[i]);
}
}
D:求一个图的最小环,如果两点按位与大于0,那么两点间建一条边。
思路
很容易发现,如果二进制第
i
i
i位出现的次数大于2,那么最小环一定是
3
3
3。 因此我们可以考虑:对于
n
n
n个点,当非0点的个数很多的时候(其实大于64*3就可以了,这样保证至少有一个二进制位出现3次),最小环个数一定是3。
因此去除非0点后,对于小数据我们可以直接floyd暴力求解最小环,剩下情况直接特判 3 3 3就好了
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<stdio.h>
#include<string.h>
#include<queue>
#include<cmath>
#include<map>
#include<set>
#include<vector>
using namespace std;
#define inf 0x3f3f3f3f
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define mem(a,b) memset(a,b,sizeof(a));
#define lowbit(x) x&-x;
#define debugint(name,x) printf("%s: %d\n",name,x);
#define debugstring(name,x) printf("%s: %s\n",name,x);
typedef long long ll;
typedef unsigned long long ull;
const double eps = 1e-6;
const int maxn = 1e5+5;
const int mod = 1e9+7;
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-'0';ch=getchar();}
return x*f;
}
int n;
ll a[maxn];
vector<int>vec[70];
int mp[605][605];
int num;
int floyd()
{
n = num;
int mincircle = n+100;
int Dist[n+1][n+1];
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
{
Dist[i][j] = mp[i][j];
}
for(int k = 1; k <= n; k++)
{
for(int i = 1; i < k; i++)
for(int j = i+1; j < k; j++)
{
mincircle = min(mincircle,Dist[i][j]+mp[j][k]+mp[k][i]);
}
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
{
Dist[i][j] = min(Dist[i][j],Dist[i][k] + Dist[k][j]);
}
}
return mincircle;
}
int main() {
scanf("%d",&n);
for(int i = 1; i <= n; i++){
scanf("%lld",&a[i]);
ll c = a[i];
if(c) num++;
int cnt = 0;
while(c){
if(c&1) vec[cnt].push_back(num);
cnt++;
c >>= 1;
}
}
if(num > 500) {
puts("3");
return 0;
}
for(int i = 0; i < 505; i++)
for(int j = 0; j < 505; j++) mp[i][j] = n+100;
for(int i = 0; i <= 64; i++){
for(int j = 0; j < vec[i].size(); j++){
int u = vec[i][j];
mp[u][u] = 0;
for(int k = 0; k < vec[i].size(); k++){
if(j != k){
int v = vec[i][k];
mp[u][v] = mp[v][u] = 1;
}
}
}
}
int ans = floyd();
if(ans > n) puts("-1");
else
printf("%d\n",ans);
}