思路:如果奇数超过1个,那么答案是0;否则,所有数的gcd就是答案。
构造方案:每个数都除以gcd,如果奇数个仍旧不超过1个,找奇数个那个在中间(如果没有奇数默认a),其他的平均分到两边。
如果奇数个数超过1个,为了保证中间点之间的每个字母个数是偶数个,那么就拿上种情况的两个构造一段(两个对称拼成一段)。
代码:
#include<bits/stdc++.h> using namespace std; int a[26]; const int N=2e6; char s[N]; int gcd(int a,int b) { return b?gcd(b,a%b):a; } int main() { ios::sync_with_stdio(false); cin.tie(0); int n; cin>>n; int cnt=0; for(int i=0;i<n;i++) { cin>>a[i]; if(a[i]&1)cnt++; } if(n==1) { cout<<a[0]<<endl; for(int i=0;i<a[0];i++) cout<<'a'; cout<<endl; return 0; } if(cnt>=2) { cout<<0<<endl; for(int i=0;i<n;i++) { for(int j=0;j<a[i];j++)cout<<(char)(i+'a'); } cout<<endl; return 0; } int ans=gcd(a[0],a[1]); for(int i=2;i<n;i++) ans=gcd(ans,a[i]); int l=1e6,r=1e6+1; int index=0; for(int i=0;i<n;i++) { a[i]/=ans; if(a[i]&1)index=i; } cnt=0; for(int i=0;i<n;i++) { if(a[i]&1)cnt++; } for(int i=0;i<a[index];i++) { s[r++]='a'+index; //cout<<s[r-1]<<endl; } bool flag=true; for(int i=0;i<n;i++) { if(i==index)continue; while(a[i]!=0) if(flag) { s[l--]='a'+i; a[i]--; flag=false; } else { s[r++]='a'+i; a[i]--; flag=true; } } string as; for(int i=l+1;i<r;i++)as+=s[i]; if(cnt>=2)for(int i=r-1;i>l;i--)as+=s[i]; cout<<ans<<endl; if(cnt>=2)ans/=2; for(int i=0;i<ans;i++) cout<<as; cout<<endl; return 0; }