Educational Codeforces Round 83 (Rated for Div. 2)
A.Two Regular Polygons
题解
这个结论很好猜吧,肯定是倍数关系啦。
要证明的话,你就在那个\(n\) 边形的每一条边都扣出\(n/m\) 个角就可以了
#include<bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
typedef long long LL;
typedef pair<int,int> PII;
#define X first
#define Y second
inline int read()
{
int x=0,f=1;char c=getchar();
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=x*10+c-'0';c=getchar();}
return x*f;
}
int T,n,m;
int main()
{
T=read();
while(T--)
{
n=read();m=read();
if(n%m==0)puts("YES");
else puts("NO");
}
return 0;
}
B.Bogosort
题解
既然是个构造,让\(j-a_j≠i-a_i\),那么由于第一项单增,我们只需要让\(a_i\) 递减排列就不可能出现相等情况了
#include<bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
typedef long long LL;
typedef pair<int,int> PII;
#define X first
#define Y second
inline int read()
{
int x=0,f=1;char c=getchar();
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=x*10+c-'0';c=getchar();}
return x*f;
}
const int maxn=110;
int T,n,a[maxn],b[maxn];
int main()
{
T=read();
while(T--)
{
n=read();
for(int i=1;i<=n;i++)a[i]=read();
sort(a+1,a+n+1);
for(int i=n;i>=2;i--)printf("%d ",a[i]);
printf("%d\n",a[1]);
}
return 0;
}
C.Adding Powers
题解
把每个数拆成\(k\) 进制。依题意,每一位至多是1,否则就不行。
#include<bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
typedef long long LL;
typedef pair<int,int> PII;
#define X first
#define Y second
inline LL read()
{
LL x=0,f=1;char c=getchar();
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=x*10+c-'0';c=getchar();}
return x*f;
}
int T,n,k,add[70];
LL a;
int main()
{
T=read();
while(T--)
{
mem(add,0);
n=read();k=read();
bool ok=0;
for(int i=0;i<n;i++)
{
a=read();
LL tmp=a;
int j=0;
while(tmp)
{
add[j]+=(tmp%k);
if(add[j]>1){ok=1;break;}
j++;
tmp=tmp/k;
}
}
if(!ok)puts("YES");
else puts("NO");
}
return 0;
}
D.Count the Arrays
题解
结论题
最多只能有两个数相等,所以不考虑重复的,有\(n-1\) 个数,从\(m\) 个数里选\(n-1\) 个,有\(C^{n-1}_m\) 种,然后最大的数当峰值,将剩下\(n-2\) 个数,分成两组一左一右,又有\(2^{n-2}\) 种,最后把重复的再算上,乘以一个\(n-2\) 就好了 ,再添加重复元素的时候需要注意,会产生多一倍的重复情况,例如\((1,2|3,1)\) 可以由\((1,2|3)\) 复制一个1以及\((2|3,1)\) 复制一个1获得,所以需要再除以2。
答案为\(C^{n-1}_m*(n-2)*2^{n-3}\)
需要特判\(n=2\)的情况(我还因此炸了两次)
考完才发现没有必要写快速幂
#include<bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
typedef long long LL;
typedef pair<int,int> PII;
#define X first
#define Y second
inline int read()
{
int x=0,f=1;char c=getchar();
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=x*10+c-'0';c=getchar();}
return x*f;
}
const int MOD=998244353;
int n,m;
LL inv[200010];
LL C(int n,int m)
{
LL res=1;
for(int i=1;i<=m;i++)res=(res*(LL)(n-i+1)%MOD*inv[i])%MOD;
return res;
}
LL quickpow(LL a,int N)
{
LL res=1;
while(N)
{
if(N&1)res=(res*a)%MOD;
a=a*a%MOD;
N>>=1;
}
return res;
}
int main()
{
inv[1]=1;
for(int i=2;i<=200000;i++)inv[i]=((LL)(MOD-MOD/i)*(LL)inv[MOD%i])%MOD;
n=read();m=read();
if(n==2)printf("%d\n",0);
else printf("%lld\n",C(m,n-1)*quickpow(2,n-3)%MOD*(LL)(n-2)%MOD);
return 0;
}
E.Array Shrinkin
题解
设\(dp[i][j]\) 表示区间\([i,j]\) 最后能化成什么数,这个可以在\(O(n^3)\) 时间内解决,然后最后线段覆盖求最小值即可。
#include<bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
typedef long long LL;
typedef pair<int,int> PII;
#define X first
#define Y second
inline int read()
{
int x=0,f=1;char c=getchar();
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=x*10+c-'0';c=getchar();}
return x*f;
}
const int maxn=510;
int n,a[maxn],dp[maxn][maxn],vis[maxn][maxn],f[maxn];
int DP(int L,int R)
{
if(vis[L][R])return dp[L][R];
vis[L][R]=1;
int &res=dp[L][R];
if(R<L)return -1;
if(R==L)return res=a[L];
for(int i=L;i<R;i++)
if(DP(L,i)==DP(i+1,R) && DP(L,i)!=-1)return res=DP(L,i)+1;
return res;
}
int main()
{
mem(dp,-1);
n=read();
for(int i=1;i<=n;i++)a[i]=read();
DP(1,n);
mem(f,42);
f[0]=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=i;j++)
if(dp[j][i]!=-1)f[i]=min(f[i],f[j-1]+1);
printf("%d\n",f[n]);
return 0;
}
事后补题
F. Attack on Red Kingdom
题解
一定会来的
博弈论。。。有点害怕