1.Olesya and Rodion
题目链接:
http://codeforces.com/problemset/problem/584/A
解题思路:
Two cases: t = 10 and t ≠ 10.
If t = 10 then there are two cases again :). If n = 1 then answer is - 1 (because there is not any digit divisible by t). If n > 1, then answer, for example, is '1111...110' (contains n - 1 ones).
If t < 10 then answer, for example, is 'tttttttt' (it, obviously, divisible by t).
题目大意:
给你二个数n、t,求一个能够被t整除的n位数,存在多组解时输出任意一组,不存在时输出“-1”。
AC代码:
#include <bits/stdc++.h>
using namespace std;
int main(){
int n,t;
while(~scanf("%d%d",&n,&t)){
if(t == 10){
if(n == 1)
printf("-1\n");
else{
n--;
for(int i = 0; i < n; i++)
printf("1");
printf("0\n");
}
}
else{
for(int i = 0; i < n; i++)
printf("%d",t);
printf("\n");
}
}
return 0;
}
2.Kolya and Tanya(排列组合)
题目链接:
http://codeforces.com/problemset/problem/584/B
解题思路:
The number of ways to choose ai (without any conditions) — 33n. Let A be the number of ways to choose ai with condition that in every triangle gnomes have 6 coins. Then answer is 33n - A.
Note that we can separate all gnomes on n independent triangles (i-th triangle contains of ai, ai + n, ai + 2n, i < n). So we can count answer for one triangle and then multiply the results. To count answer for one triangle, we can note that there are 7 ways to choose gnomes with 6coins (all permutations 1, 2, 3 and 2, 2, 2).
So answer is — 33n - 7n. We count it in O(n).
题目大意:在一个圆上,3n个点依次标号,然后标号为i,i+n,i+2n的点连成三角形。然后每个点分配一个值(在1-3范围内)。然后只要有一个
三角形的点的值的和不为6就成功。问有多少种分配方案。
算法思想:
排列组合。总共3^3n个可能,减去7^n个不可能的结果。因为要么是222要么是123才能有6,然后222只有1种123可以6种,加起来
一个三角形的不成功的情况有7种。
AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9+7;
ll pow_mod(ll base,int n){
ll ans = 1;
while(n){
if(n&1)
ans = (ans*base)%mod;
base = (base*base)%mod;
n >>= 1;
}
return ans;
}
int main(){
int n;
while(~scanf("%d",&n)){
printf("%lld\n",(pow_mod(27LL,n)-pow_mod(7LL,n)+mod)%mod);
}
return 0;
}
3.Marina and Vasya(构造)
题目链接:
http://codeforces.com/problemset/problem/584/C
解题思路:
Let's find a string that will be equal to s1 in k = n - t positions and equal to s2 in k = n - t positions. Let's denote q = quantity of i thats1i = s2i. If k ≤ q, then let's take k positions such that s1pos = s2pos and put in answer the same symbols. Then put in other n - k positions symbols, which are not equal to corresponding in s1 and s2 (we can do it, because we have 26 letters).
Now k > q. So, if there is an answer, where exists pos such that s1pos = s2pos, s1pos ≠ anspos, let's denote ansi = s1i, and then in any position such that s1i ≠ s2i = ansi and s1i = ansi (and in the same position in s2) we will choose ai, such that ai ≠ s1i and ai ≠ s2i (we can do it because k > q). So, for every position from q we can put symbols, equal to corresponding symbols in s1 and s2. Now we have strings s1, s2 of length n - q (such that s1i ≠ s2i for every i) and we should find string ans such that f(ans, s1) = f(ans, s2). We know thats1i ≠ s2i, so ansi may be equal to corresponding in s1 or to corresponding in s2 or not equal to s1i and to s2i. So, we need, at least,2(k - q) symbols in answer to make f(s1, ans) = k - q and f(s2, ans) = k - q. Consequently, if n - q < 2(k - q), the answer is - 1, and else just put first k - q symbols in answer from s1, next k - q symbols from s2, and others won't be equal to corresponding in s1 and s2.
Solution works in O(n).
题目大意:给你两个长度为n的串a、b,然后要你找出一个新串c,这个串c和之前两个串不同的字符数目恰好为t个。
算法思想:
反过来想,令same为g(a,c),先找a[i],b[i]两个串相同的位置并标记,相同的个数为cnt,如果same > cnt+(n-cnt)/2,则不能同时满
足g(a,c)=same,g(a,c)=same。所以输出-1即可。然后先使c[i]满足a[i]=b[i]的情况。接着再满足c[i]=a[i]和c[i]=b[i]的情况,剩下的全是
不相等的情况,一一枚举即可。
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
char a[100005],b[100005],c[100005];
int vis[100005];
int main(){
int n,t;
while(~scanf("%d%d",&n,&t)){
memset(c,0,sizeof(c));
memset(vis,0,sizeof(vis));
scanf("%s",a);
scanf("%s",b);
int flag = 0,same = n-t,cnt = 0;
for(int i = 0; i < n; i++){
if(a[i] == b[i]){
vis[i] = 1;
cnt++;
}
}
if(same > cnt+(n-cnt)/2){
printf("-1\n");
continue;
}
for(int i = 0; i < n; i++){
if(same && vis[i]){
c[i] = a[i];
same--;
}
}
cnt = same;
for(int i = 0; i < n; i++){
if(cnt && !c[i]){
c[i] = a[i];
cnt--;
}
}
cnt = same;
for(int i = 0; i < n; i++){
if(cnt && !c[i]){
c[i] = b[i];
cnt--;
}
}
for(int i = 0; i < n; i++){
if(!c[i]){
for(char j = 'a';; j++){
if(j != a[i] && j != b[i]){
c[i] = j;
break;
}
}
}
}
c[n] = '\0';
printf("%s\n",c);
}
return 0;
}
4.Dima and Lisa(哥德巴赫猜想)
题目链接:
http://codeforces.com/problemset/problem/584/D
解题思路:
There is a fact that the distance between adjacent prime numbers isn't big. For n = 109 maximal distanse is 282. So let's find maximal prime p, such that p < n - 1 (we can just decrease n while it's not prime(we can check it in )). We know that n - p < 300. Now we have even (because n and p are odd) number n - p and we should divide it into a sum of two primes. As n - p < 300, we can just iterate over small primes P and check if P is prime and n - p - P is prime. You can check that there is a solution for all even numbers less than300 by bruteforce.
题目大意:
给你一个数n,要你把n拆成1-3个素数的和。n是奇数。
算法思想:
哥德巴赫猜想:任一大于2的偶数都可写成两个质数之和。
AC代码:
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
bool is_prime(int n){
int tmp = sqrt(n*1.0);
for(int i = 2; i <= tmp; i++)
if(n%i == 0)
return false;
return n > 1? true: false;
}
int main(){
int n;
scanf("%d",&n);
if(is_prime(n))
printf("1\n%d\n",n);
else if(is_prime(n-2))
printf("2\n2 %d\n",n-2);
else{
n -= 3;
for(int i = 2; ; i++){
if(is_prime(i) && is_prime(n-i)){
printf("3\n3 %d %d\n",i,n-i);
break;
}
}
}
return 0;
}
5.Anton and Ira(置换群)
题目链接:
http://codeforces.com/problemset/problem/584/E
解题思路:
We can consider that we pay 2|i - j| coins for swap (we can divide answer in the end). Then we can consider that we pay |i - j| coins for moving pi and |i - j| for moving pj. So, if x was on position i and then came to position j, then we will pay at least |i - j| coins. Then the answer is at least (pp — position k in permutation p, and ps — position k in permutation s). Let's prove that this is the answer by showing the algorithm of making swaps.
Let's consider that permutation s is sorted (our task is equal to it). Then we will put numbers from n to 1 on their positions.
How we can put n on its position? Denote ppos = n. Let's prove that there exists a position pos2 such that pos < pos2 andppos2 ≤ pos(then we will swap ppos2 with n (and both numbers will move to their final positions and n will move to the right, so we can repeat this process until n returns to its position)). We can note that there are only n - pos positions that are bigger than pos. And how many numbers on these positions can be bigger than pos? We can say that answer is n - pos, but it's incorrect, because n is bigger thanpos, but posn ≤ pos. Now we can use Pigeonhole principle and say that position x, such that x > pos and px ≤ pos exists.
But now our algorithm is O(n3). How we can put n in its position in O(n) operations? Let's move the pointer to the right while number is bigger than pos. Then swap n with found number. After we can move pointer from new n's position, so pointer always moves to the right and will not do more then n steps.
题目大意:给你一个1-n的排列,让你通过交换i,j变成另外一个1-n的排列,交换的代价为abs(i-j)。问你最小代价,然后输出交换的步骤。
AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> P;
const int N = 2005;
int a[N];
int b[N];
int pos1[N];
int pos2[N];
vector<P> res;
vector<P>::iterator it;
int main(){
int n;
scanf("%d",&n);
for(int i = 1; i <= n; i++)
scanf("%d",&a[i]);
for(int i = 1; i <= n; i++){
scanf("%d",&b[i]);
pos1[b[i]] = i;
}
int ans = 0;
for(int i = 1; i <= n; i++){
a[i] = pos1[a[i]];
pos2[a[i]] = i;
}
for(int num = n; num >= 1; num--){
int pos = pos2[num];
if(pos == num)
continue;
for(int i = pos; i <= num; i++){
if(a[i] <= pos){
ans += i - pos;
swap(pos2[a[i]], pos2[a[pos]]);
swap(a[i], a[pos]);
res.push_back(P{i, pos});
pos = i;
}
}
}
printf("%d\n",ans);
printf("%d\n",res.size());
for(it = res.begin(); it != res.end(); it++)
printf("%d %d\n", (*it).first, (*it).second);
}