标签: codeforces
A. Links and Pearls
代码
expand
```cpp
#include
#include
using namespace std;
typedef long long ll;
const ll MOD=1e9+7;
int main(int argc, char const *argv[])
{
string s;
cin>>s;
int a=0,b=0;
for (int i = 0; i < s.size(); ++i)
{
if(s[i]=='-') a++;
else b++;
}
if(b==0||a%b==0) printf("YES
");
else printf("NO
");
return 0;
}
```
B. Marlin
代码
expand
```cpp
#include
#include
using namespace std;
typedef long long ll;
const ll MOD=1e9+7;
char a[4][120];
int main(int argc, char const *argv[])
{
int n,k;
scanf("%d%d", &n,&k);
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < n; ++j)
{
a[i][j]='.';
}
}
printf("YES
");
if(k&1){
a[1][n/2]='#';
k--;
}
else if(k==2*(n-2)){
a[1][n/2]=a[2][n/2]='#';
k-=2;
}
for (int i = 1; i < n/2 && k > 0; ++i)
{
a[1][n/2-i]=a[1][n/2+i]='#';
k-=2;
}
for (int i = 1; i < n/2 && k > 0; ++i)
{
a[2][n/2-i]=a[2][n/2+i]='#';
k-=2;
}
for (int i = 0; i < 4; ++i)
{
printf("%s
", a[i]);
}
return 0;
}
```
C. Posterized
代码
expand
```cpp
#include
#include
#include
using namespace std;
typedef long long ll;
const ll MOD=1e9+7;
const int maxn=100050;
int f[300],x,sz[300];
int main(int argc, char const *argv[])
{
int n,k;
scanf("%d%d", &n,&k);
memset(f,-1,sizeof f);
for (int i = 0; i < n; ++i)
{
scanf("%d", &x);
if(f[x]!=-1) printf("%d ", f[x]);
if(f[x]==-1){
int s=0;
for (int j = max(0,x-k+1); j <= x; ++j)
{
if(f[j]==-1||x-f[j]+1<=k){
s=j;
break;
}
}
if(f[s]==-1){
for (int j = s; j <= x; ++j)
{
f[j]=s;
}
}
else{
for (int j = s; j <= x; ++j)
{
f[j]=f[s];
}
}
printf("%d ", f[x]);
}
}
return 0;
}
```
D. Perfect Groups
题意
对于每个$k in[1,n] $,输出给定的数组有多少个子数组满足:最少可划分为k个集合就能使得每个集合中的元素两两相乘得到平方数。
分析
对于每个元素分解因数,将分解后每个质数幂模(2)得到一个新的元素,值相等的可满足相乘为平方数。
注意(n^2)统计的时候,不能用set
或者unordered_set
,否则会TLE.还有0元素要特别处理一下。
expand
```cpp
#include
#include
#include
using namespace std;
const int maxn=5050;
int a[maxn],ans[maxn];
int prime[15050],pz;
bool notprime[15050];
void get_prime(){
notprime[0]=notprime[1]=true;
for(int i = 2; i < 15050; ++i){
if(!notprime[i]){
prime[pz++]=i;
for(int j = i*i; j < 15050; j+=i){
notprime[j]=true;
}
}
}
}
const int N=1e8;
bool vis[N*2+5];
int main()
{
get_prime();
int n;
scanf("%d", &n);
for(int i = 1; i <= n; ++i){
int x;
scanf("%d", &x);
if(x==0) continue;
a[i]=1;
if(x<0) x=-x,a[i]=-1;
for(int k = 0; prime[k]*prime[k] <= x; ++k){
int j=prime[k];
if(x%j==0){
int cnt=0;
while(x%j==0) x/=j,cnt++;
if(cnt&1) a[i]*=j;
}
}
if(x>1) a[i]*=x;
}
for(int i = 1; i <= n; ++i){
int cnt=0;
for(int j = i; j <= n; ++j){
if(!vis[a[j]+N]) cnt++,vis[a[j]+N]=true;
ans[cnt-(int)(cnt>1&&vis[N])]++;
}
for(int j = i; j <= n; ++j){
vis[a[j]+N]=false;
}
}
for(int i = 1; i <= n; ++i) printf("%d ", ans[i]);
}
```
E. The Number Games
分析
转换为选择(n-k)个点使得点的权值和最大。
因为对于编号为(x)的点,所有编号小于(x)的点的权值和小于(x)的权值,所以我们优先选择编号大的点。
- 如果只能选择一个,那么选择(n)号点。
- 如果当前已经选择了一些点,剩余点编号最大的点为(t),我们可以先使用倍增求出(t)到已选择树的最小距离,那么这一最小距离上的点都要放到连到树上。如果连上不会使总点数超过(n-k)就连上,否则再枚举权值稍小的点。
代码
expand
```cpp
#include
#include
#include
#include
using namespace std;
const int maxn=1000050;
struct Edge{
int v,nxt;
}e[maxn*2];
int h[maxn],tot;
void addEdge(int x,int y){
e[++tot]=(Edge){y,h[x]};
h[x]=tot;
}
int n,k;
int f[maxn][30],dep[maxn];
void dfs(int x,int fa){
dep[x]=dep[fa]+1;
f[x][0]=fa;
for(int i = 1; f[x][i-1]; ++i){
f[x][i]=f[f[x][i-1]][i-1];
}
for(int i = h[x]; i ; i = e[i].nxt){
if(e[i].v!=fa) dfs(e[i].v,x);
}
}
bool mark[maxn];
void insert(int x){
if(mark[x]) return;
int p=x;
for(int i = 20; i >= 0; --i){
int t=f[p][i];
if(!mark[t]) p=f[p][i];
}
p=f[p][0];
if(k
F. Cactus to Tree
留坑
expand
```cpp
</details>