比赛链接:Dashboard - Codeforces Round #847 (Div. 3) - Codeforces
目录
A. Polycarp and the Day of Pi
B. Taisia and Dice
C. Premutation
D. Matryoshkas
E. Vlad and a Pair of Numbers
A. Polycarp and the Day of Pi
题意:求出一个数字的前几位和 π 相同。
string k="314159265358979323846264338327";
void solve() {
string s;
int p=0;
cin>>s;
while(p<30&&s[p]==k[p])p++;
cout<<p<<endl;
}
B. Taisia and Dice
题意:已知道所有骰子的数量,骰子的点数总和,以及拿走一个最大值的点数总和,请构造所有骰子的点数。
思路:从题目中我们就能得到骰子的最大值了,所以我们先将所有骰子的值都设为最大值,若当前骰子的总点数大于我们期望的总点数就减少它。
void solve() {
int n,s,r;
cin>>n>>s>>r;
int k=s-r;
int sum=k*n;
FOR(1,n)a[i]=k;
FOR(1,n) {
if(sum-(k-1)>=s)a[i]=1,sum-=k-1;
else if(sum-(k-1)<s) {
a[i]-=(sum-s);
break;
}
}
FOR(1,n)cout<<a[i]<<" \n"[i==n];
}
C. Premutation
题意:一个长度为 n 的排列,将 n个这样的排列每个去掉一位然后打乱。根据打乱后的排列求出原排列。
思路:排列的第一个数在每个数组的第一个位置总共会出现n-1次,由此我们可以确定排列的第一个数为k,然后我们找到那个数组第一个数不是k的数组,这个数组就是排列第2~n的数字,输出第一个数并且输出该数组即可。
void solve() {
mem(mp,0);
int n,k;
cin>>n;
FOR(1,n) {
FORj(1,n-1)cin>>a[i][j];
mp[a[i][1]]++;
}
FOR(1,n)if(mp[i]==n-1) k=i;
cout<<k<<" ";
FOR(1,n) {
if(a[i][1]!=k)FORj(1,n-1)cout<<a[i][j]<<" \n"[j==n-1];
}
}
D. Matryoshkas
题意:给定一个集合,将该集合分成若干个由连续正整数组成的集合,求分成集合的数量的最小值。
思路:若一个数前面没连续数字,则该数对于答案的贡献为该数出现的次数,但若该数前一个数出现过了,那么该数的一部分就能合并到前一个数里面,减少了上一个数出现次数的贡献(该数贡献最多减少至0)。
void solve() {
map<int,int>mp;
int n,x,ans=0;
cin>>n;
FOR(1,n) {
cin>>x;
mp[x]++;
}
for(auto [x,y]:mp)
ans+=max(0ll,y-mp[x-1]);
cout<<ans<<endl;
}
E. Vlad and a Pair of Numbers
题意:给你一个x ,求出两个数字a,b使得 a+b=2*x 并且a⊕b=x 。
思路:有个结论是我从别人的博客看到的:
博客链接: Codeforces Round #847 (Div. 3) E(数学) - 知乎
由此我们可以得出a=x/2,b=3*x/2,最后代入验证一下即可。
void solve() {
int x;
cin>>x;
int a=x/2,b=3*x/2;
if(!((a+b)&1)&&(a^b)==(a+b)/2)cout<<a<<" "<<b<<endl;
else cout<<-1<<endl;
}