Codeforces #137 div2

A.水题,观察下k及其后面是不是都是同样的数字判断是否为-1,否则看前面有多少个和a[k]后面的数字不一样的,来判断需要调整多少次。

B.水题,交换的时候换下标号就行了。

C.有意思的一题,问分数约分的结果,突然记起来看过一张图:

Codeforces #137 div2_第1张图片

回到正题……

要求n和m在10^5范围内,那么如果先全部分解质因子之后约分,再将结果随机组合乘起来输出就很有可能就会超出这个范围,因此,决定在约分后,该位置的数一定要是约分前在该位置的数的约数,所以就先对所有分子和所有分母都分解质因子,然后对于原来的分子,逐个遍历分解质因子,如果该质因子在分母中的数目大于0,那么就将其约掉,也就是该质因子在分母中的数目减1,如果等于0,说明不能被约掉,就用一个新变量存起来,有不能被约掉的就在这个变量上累乘就行了,最后约分的结果就是这些新变量了。

代码

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

int p[5000];
bool prime[5000];
int a[100005];
int b[100005];
int up;
map <int,int> fm;
map <int,int> fz;

void Prime()
{
    int i,j;
    memset(prime,0,sizeof(prime));
    for (i=2;i<=3500;i++)
    {
        if (prime[i]==1) continue;
        p[up++]=i;
        for (j=i*i;j<=3500;j+=i)
        {
            prime[j]=1;
        }
    }
}

int main()
{
    int i,j,n,m,t,now;
    up=0;
    Prime();
    scanf("%d%d",&n,&m);
    for (i=0;i<n;i++)
    {
        scanf("%d",&a[i]);
        t=a[i];
        for (j=0;j<up;j++)
        {
            if (t==1) break;
            while(t%p[j]==0)
            {
                fm[p[j]]++;
                t/=p[j];
            }
        }
        if (t!=1) fm[t]++;
    }
    for (i=0;i<m;i++)
    {
        scanf("%d",&b[i]);
        t=b[i];
        for (j=0;j<up;j++)
        {
            if (t==1) break;
            while(t%p[j]==0)
            {
                t/=p[j];
                fz[p[j]]++;
            }
        }
        if (t!=1) fz[t]++;
    }
    map <int,int>::iterator it;
    printf("%d %d\n",n,m);
    for (i=0;i<n;i++)
    {
        t=a[i];
        now=1;
        for (j=0;j<up;j++)
        {
            if (t==1) break;
            while (t%p[j]==0)
            {
                if (fz[p[j]]>0) fz[p[j]]--;
                else now*=p[j];
                t/=p[j];
            }
        }
        if (t!=1)
        {
            if (fz[t]>0) fz[t]--;
            else now*=t;
        }
        printf("%d ",now);
    }
    printf("\n");
    for (i=0;i<m;i++)
    {
        t=b[i];
        now=1;
        for (j=0;j<up;j++)
        {
            if (t==1) break;
            while(t%p[j]==0)
            {
                if (fm[p[j]]>0) fm[p[j]]--;
                else now*=p[j];
                t/=p[j];
            }
        }
        if (t!=1)
        {
            if (fm[t]>0) fm[t]--;
            else now*=t;
        }
        printf("%d ",now);
    }
    printf("\n");
    return 0;
}

D.突然变简单了……orz

水题,将a数组从小到大排序,将b数组从大到小排序,然后对于b的每个数,找到能够使得与它相加大于等于x而且没被用过的数,然后标记为使用就行了,因为在a中数字是递增的,因此寻找的时候只要扫一遍a数组即可,复杂度O(n)。

ps:最好的名次肯定是No.1了……

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

int a[100005];
int b[100005];

bool cmp(int x,int y)
{
    return x<y;
}

int main()
{
    int i,j,n,k,ans,l,m,cnt;
    scanf("%d%d",&n,&k);
    for (i=0;i<n;i++)
    {
        scanf("%d",&a[i]);
    }
    for (i=0;i<n;i++)
    {
        scanf("%d",&b[i]);
    }
    sort(a,a+n);
    sort(b,b+n,cmp);
    cnt=0;
    l=0;
    for (i=n-1;i>=0;i--)
    {
        while(l<n && b[i]+a[l]<k) l++;
        if (l==n) break;
        cnt++;
        l++;
    }
    printf("1 %d\n",cnt);
    return 0;
}

E.水题,入门的矩阵递推。

不解释。

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

#define MOD 1000000007

typedef struct
{
    __int64 m[55][55];
}Matrix;

Matrix b;
char str[10];
Matrix a;
int m;

Matrix Mul(Matrix x,Matrix y)
{
    Matrix tag;
    int i,j,k;
    for (i=0;i<m;i++)
    {
        for (j=0;j<m;j++)
        {
            tag.m[i][j]=0;
            for (k=0;k<m;k++)
            {
                tag.m[i][j]=(tag.m[i][j]+(x.m[i][k]*y.m[k][j])%MOD)%MOD;
            }
        }
    }
    return tag;
}

int GetNum(char c)
{
    if (c>='a' && c<='z') return c-'a';
    return 26+c-'A';
}

int main()
{
    int i,j,k;
    __int64 n,cnt;
    scanf("%I64d%d%d",&n,&m,&k);
    for (i=0;i<m;i++)
    {
        for (j=0;j<m;j++)
        {
            a.m[i][j]=1;
        }
        b.m[i][0]=1;
    }
    for (i=0;i<k;i++)
    {
        scanf("%s",str);
        a.m[GetNum(str[0])][GetNum(str[1])]=0;
    }
    n--;

    while(n)
    {
        if (n&1) b=Mul(a,b);
        a=Mul(a,a);
        n>>=1;
    }
    cnt=0;
    for (i=0;i<m;i++)
    {
        cnt=(cnt+b.m[i][0])%MOD;
    }
    printf("%I64d\n",cnt);
    return 0;
}


你可能感兴趣的:(Codeforces #137 div2)