Codeforces Round #324 (Div. 2) (快速判断素数模板)

蛋疼的比赛,当天忘了做了,做的模拟,太久没怎么做题了,然后C题这么简单的思路却一直卡到死,期间看了下D然后随便猜了下,暴力了下就过了。

A.找一个能被t整除的n位数,那么除了<=10以外,其他都可以用长度为n的10或100,1000 。。。 来往上加几个数而得到

#include <iostream>
#include <stdio.h>
#include <set>
#include <algorithm>
#include <string.h>
using namespace std;

int getwei(int x)
{
    int sum=0;
    while(x)
    {
        sum++;
        x=x/10;
    }
    return sum;
}
int main()
{
    int n,t;
    scanf("%d%d",&n,&t);
    if(n==1&&t==10)
        printf("-1");
    else if(n==1)
    {
        printf("%d",t);
    }
    else
    {
        int save;
        for(int i=10;i<99;i++)
        {
            if(i%t==0)
            {
                save=i;
                break;
            }
        }
        printf("%d",save);
        for(int i=2;i<n;i++)
        {
            printf("0");
        }
    }
    return 0;
}

B.很好找的公式题,((27^n-7^n)%MOD+MOD)%MOD。n很不大所以直接暴力就行了。

#include <iostream>
#include <stdio.h>
#include <set>
#include <algorithm>
#include <string.h>
using namespace std;
#define MOD 1000000007

int main()
{
    int n;
    scanf("%d",&n);
    long long tmp=1;
    long long tmp1=1;
    for(int i=0;i<n;i++)
    {
        tmp=tmp*27;
        tmp%=MOD;
        tmp1=tmp1*7;
        tmp1%=MOD;
    }
    tmp-=tmp1;
    tmp= (tmp%MOD+MOD)%MOD;
    cout<<tmp<<endl;
    return 0;
}

C.思维题,给出了长度为n的两个字符串a和b,要你找到一个c串使得c串分别与a串和b串的相同位置不同字符数恰好为t。可以这样想,如果在某个位置i上

如果a[i]==b[i],那么可以贡献a和b相异值1或0

如果a[i]!=b[i],那么要么贡献串a的相异值为1,要么贡献b的相异值为1,要么同时贡献a和b的相异值1.

因为ab的相异值必须得相等,那么最小的相异值为:所有a[i]!=b[i]的个数和为sumaneb,(sumaneb+1)/2 。如果这个值>t那么必定无解,否则一定有解。

如果有解,因为a[i]==b[i]的情况是可控的,所以尽量先把这种情况全部加进来,如果这种情况全部算进来却还是小于t,那么就将a[i]!=b[i]的情况变成对a和b同时贡献的情况。

这样想其实挺复杂的,判断情况就要想,还得推公式一种情况弄个c串。

看了大神的代码立马觉得涨姿势,果真自己的思路太弱。大神的做法是先得出一个c串,使得和ab串完全不相等。然后从a[i]==b[i]的情况中一个一个加入相等的情况,如果全部设为相等后还是不够,那就冲a[i]!=b[i]中加入相等的,如果全部加完还是不行就输出-1.

用这种思路的大神开场不到20分钟就把这题A了。 。。

#include <iostream>

using namespace std;

int n, t;
string a;
string b;
string c;

int main() {
    cin >> n >> t;
    cin >> a >> b;
    int u = n;
    c = a;
    for (int i = 0; i < n; i++) {
        char x = ‘a‘;
        if (a[i] == x || b[i] == x) x = ‘b‘;
        if (a[i] == x || b[i] == x) x = ‘c‘;
        c[i] = x;
    }
    for (int i = 0; i < n; i++) {
        if (a[i] == b[i] && t != u) {
            c[i] = a[i];
            u--;
        }
    }
    int z = 0;
    for (int i = 0; i < n; i++) {
        if (a[i] == b[i] || u == t) continue;
        if (z == 0) {c[i] = a[i]; z = 1;}
        else {c[i] = b[i]; u--; z = 0;}
    }
    if (u == t) cout << c << "\n";
    else cout << "-1\n";
}

D.给出一个3到10^9的整数n,然后要求输出三个素数a,b,c使得a+b+c=n.

哥德巴赫猜想:任何一个大于二的偶数都可以分解为两个素数和。

我的猜想是任意一个<=10^9的偶数,都可以快速分拆为两个素数和。所以就可以将n-3快速拆分为两个素数。

其实我这种猜想风险还太大,我使用了rabbin算法快速的判断一个数是不是素数,但是这种方法虽然快但不是绝对正确的,有一定的失误率。

#include <iostream>
#include <algorithm>
#include <string.h>
#include <stdio.h>
using namespace std;

#define S 100
typedef unsigned long long LL;

LL modular_multi(LL x,LL y,LL mo)
{
    LL t;
    x%=mo;
    for(t=0;y;x=(x<<1)%mo,y>>=1)
        if (y&1)
            t=(t+x)%mo;
    return t;
}

LL modular_exp(LL num,LL t,LL mo)
{
    LL ret=1,temp=num%mo;
    for(;t;t>>=1,temp=modular_multi(temp,temp,mo))
        if (t&1)
            ret=modular_multi(ret,temp,mo);
    return ret;
}

bool miller_rabbin(LL n)
{
    if (n==2)return true;
    if (n<2||!(n&1))return false;
    int t=0;
    LL a,x,y,u=n-1;
    while((u&1)==0) t++,u>>=1;
    for(int i=0;i<S;i++)
    {
        a=rand()%(n-1)+1;
        x=modular_exp(a,u,n);
        for(int j=0;j<t;j++)
        {
            y=modular_multi(x,x,n);
            if (y==1&&x!=1&&x!=n-1)
                return false;
            ///其中用到定理,如果对模n存在1的非平凡平方根,则n是合数。
            ///如果一个数x满足方程x^2≡1 (mod n),但x不等于对模n来说1的两个‘平凡’平方根:1或-1,则x是对模n来说1的非平凡平方根
            x=y;
        }
        if (x!=1)///根据费马小定理,若n是素数,有a^(n-1)≡1(mod n).因此n不可能是素数
            return false;
    }
    return true;
}
int main()
{
    int n;
    scanf("%d",&n);
    if(n==3) printf("1\n3");
    else if(n==5)
        printf("2\n2 3");
    else
    {
        n-=3;
        for(int i=2;i<=n;i++)
        {
            if( miller_rabbin(i) ==true)
            {
                if(miller_rabbin(n-i) == true)
                {
                    printf("3\n3 %d %d",i,n-i);
                    break;
                }
            }
        }
    }
    return 0;
}

我乱搞的算法

更确定的算法是,从n->1,先求出一个素数复杂度约等于10*sqrt(n),然后剩下来的就暴力几乎不要时间。

E.这题想了挺久的。

其实问题可以简化为

1   2   3   4  ...  n

a1 a2 a3 a4 ..   an

标号为ai的要到i位置。 然后每次交换为|i-j|费用,ij为标号。

我的思路是既然现在交换是看之间相隔的距离了,那么我把一个长的交换分拆成小的交换可以换的更好的效果。具体做法是:

对于没一个ai,如果ai>i,这ai这个数需要往右移,将这个位置标记为>

如果ai<i,这ai这个数需要往左移,将这个位置标记为<

如果ai=i,这ai这个数已经到达位置,将这个位置标记为0

比如一组数据

1 2 3 4 5

3 4 5 1 2

就可以变为

1  2 3  4  5

> > > < <

接着对于没一个相邻或者中间只隔0的><的情况进行变换,知道所有的状态都为0

比如

3 4 5 1 2 (>>><<)->

3 4 1 5 2  (>><><)->

3 1 4 5 2  (><>><)->

1 3 4 5 2  (0>>><)->

1 3 4 2 5  (0>><0)->

1 3 2 4 5  (0><00)->

1 2 3 4 5  (00000)结束。

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <string.h>
#include <math.h>
using namespace std;
#define N 2020

int f[N],tf[N];
int mylink[N];
int g[N];
int x[N*N],y[N*N];
int cnt;

int main()
{
    int ans=0;
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",tf+i);
    }
    for(int i=1;i<=n;i++)
    {
        scanf("%d",f+i);
        mylink[f[i]]=i;
    }
    for(int i=1;i<=n;i++)
    {
        tf[i]=mylink[ tf[i] ];
    }
    for(int i=1;i<=n;i++)
    {
        if(tf[i]==i) g[i]=0;
        else if(tf[i]>i) g[i]=1;
        else g[i]=-1;
    }
    while(1)
    {
        int flag=0;
        int pre=-1;
        int id=-1;
        for(int i=1;i<=n;i++)
        {
            if(g[i]==-1)
            {
                if(pre==1)
                {
                    swap(tf[id],tf[i]);
                    if(tf[id]>id) g[id]=1;
                    else if(tf[id]==id) g[id]=0;
                    else g[id]=-1;

                    if(tf[i]>i) g[i]=1;
                    else if(tf[i]==i) g[i]=0;
                    else g[i]=-1;
                    flag=1;
                    x[cnt]=id;
                    y[cnt]=i;
                    ans+=i-id;
                    cnt++;
                    if(tf[i]==i) break;
                    else
                    {
                        pre=1;
                        id=i;
                    }
                }
                else
                    pre=-1;
            }
            else if(g[i]==1)
            {
                pre=1;
                id=i;
            }
        }
        if(flag==0) break;
    }
    printf("%d\n",ans);
    printf("%d\n",cnt);
    for(int i=0;i<cnt;i++)
        printf("%d %d\n",x[i],y[i]);
    return 0;
}
时间: 2024-12-14 21:47:49

Codeforces Round #324 (Div. 2) (快速判断素数模板)的相关文章

Codeforces Round #324 (Div. 2)

今天写写cf上以前的水题,找找自信 A. Olesya and Rodion 此题要求一个能被t整除的n位数,直接t为开始,后面全部为0. 当然,需要排除位数为1但t=10的情况. #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; int main() { int n,t,i; scanf("%d%d"

Codeforces Round #324 (Div. 2) D. Dima and Lisa (哥德巴赫猜想 + 暴力)

D. Dima and Lisa Dima loves representing an odd number as the sum of multiple primes, and Lisa loves it when there are at most three primes. Help them to represent the given number as the sum of at most than three primes. More formally, you are given

Codeforces Round #324 (Div. 2)C. Marina and Vasya set

                                                      C. Marina and Vasya Marina loves strings of the same length and Vasya loves when there is a third string, different from them in exactly t characters. Help Vasya find at least one such string. Mor

Codeforces Round #324 (Div. 2) E

这题贪心,考虑先放第一个,然后从第一个数在p中的位置, 不断的往前走,和在他后面的那些数组进行交换,因为这样交换可以提高最大的效率,就是说你花费了1但是使得两个点都朝他的木匾节点减少了1 #include <iostream> #include <algorithm> #include <cstdio> #include <vector> #include <cmath> using namespace std; const int maxn=2

Codeforces Round #324 (Div. 2) D - Dima and Lisa(哥德巴赫猜想)

1 #include<bits/stdc++.h> 2 using namespace std; 3 4 /** 5 据哥德巴赫猜想:任意一个偶数可以拆成两个质数 6 n-- 直到质数 t , n-t 是偶数 , 将n-t 拆分成两个质数 7 8 */ 9 10 bool check(int x) { 11 for (int i = 2; i * i <= x; i++) 12 if (x % i == 0) return false; 13 return true; 14 } 15 1

Codeforces Round #259 (Div. 2) 解题报告

终于重上DIV1了.... A:在正方形中输出一个菱形 解题代码: 1 // File Name: a.cpp 2 // Author: darkdream 3 // Created Time: 2014年08月01日 星期五 23时27分55秒 4 5 #include<vector> 6 #include<set> 7 #include<deque> 8 #include<stack> 9 #include<bitset> 10 #inclu

Codeforces Round #258 (Div. 2)

A - Game With Sticks 题目的意思: n个水平条,m个竖直条,组成网格,每次删除交点所在的行和列,两个人轮流删除,直到最后没有交点为止,最后不能再删除的人将输掉 解题思路: 每次删除交点所在的行和列,则剩下n-1行和m-1列,直到行或列被删完为止,最多删除的次数为min(n,m),删除min(n,m)后剩余的都是行或者列(注意行与行,列与列之间不可能有交点).只需要判断min(n,m)的奇偶性. #include <iostream> #include <vector&

Codeforces Round #261 (Div. 2)

A. Pashmak and Garden 题意:已知两个顶点的坐标,如果能推断出另外两个顶点则输出(special judge).如果这两个顶点不是构成正方形的两个顶点, 则输出-1. 水题,1A,不多说. #include<cstdio> #include<iostream> #include<cstring> #include<cmath> using namespace std; int main() { int x1,x2,y1,y2,flag,x

Codeforces Round #356 (Div. 2) [Codeforces680]

此处有目录↑ Codeforces Round #356(Div. 2):http://codeforces.com/contest/680 A. Bear and Five Cards (贪心) time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output A little bear Limak plays a game. He has