Codeforces Round #480 (Div. 2)

标签: codeforces


代码

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>
原文地址:https://www.cnblogs.com/sciorz/p/9013646.html