【codevs 1376】帕秋莉·诺蕾姬

37大天使震撼来袭 新服火爆开启!!!

不动的大图书馆

题目描述

在幻想乡,帕秋莉•诺蕾姬是以宅在图书馆闻名的魔法使。这一天帕秋莉又在考虑如何加强魔法咒语的威力。帕秋莉的魔法咒语是一个仅有大写字母组成的字符串,我们考虑从’A’到’Z’分别表示0到25的数字,于是这个魔法咒语就可以看作一个26进制数。帕秋莉通过研究发现,如果一个魔法咒语所代表的数能够整除10进制数M的话,就能够发挥最大的威力。若当前的魔法咒语并不能整除M,帕秋莉只会将其中两个字符的位置交换,尽量让它能够被M整除,当然由于某些咒语比较特殊,无论怎么改变都不能达到这个目的。请你计算出她能否只交换两个字符就让当前咒语被M整除。(首位的’A’为前导0) 第1行:1个字符串,长度不超过L。 第2行:1个正整数,M 第1行:用空格隔开的2个整数,输出时先输位置靠前的那个。 如果存在多种交换方法,输出字典序最小的,比如1 3和1 5都可以达到目的,就输出1 3;1 3和2 4都行时也输出1 3。注意字符串下标从左到右依次为1到L开始。如果初始魔法咒语已经能够整除M,输出”0 0”;若无论如何也不能到达目的输出”-1 -1”。 PATCHOULI 16 4 9 对于30%的数据:1 <= L <= 10, 1 <= M <= 100 对于50%的数据:除前面30%外,1 <= L <= 500, M = 5或25或26 对于100%的数据:1 <= L <= 2,000, 1 <= M <= 200,000

输入描述

第1行:1个字符串,长度不超过L。
第2行:1个正整数,M

输出描述

第1行:用空格隔开的2个整数,输出时先输位置靠前的那个。 如果存在多种交换方法,输出字典序最小的,比如1 3和1 5都可以达到目的,就输出1 3;1 3和2 4都行时也输出1 3。注意字符串下标从左到右依次为1到L开始。如果初始魔法咒语已经能够整除M,输出”00”;若无论如何也不能到达目的输出”-1-1”。

样例输入

PATCHOULI
16

样例输出

4 9 

数据范围

对于30%的数据:1 <= L <= 10, 1 <= M <= 100 对于50%的数据:除前面30%外,1 <= L <= 500, M = 5或25或26 对于100%的数据:1 <= L <= 2,000, 1 <= M <= 200,000

乍一眼看没什么想法,先打了个目标80的骗分……?暴力……?

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int MAXL = 2000 + 5;
char L[MAXL];
int l;
int M;
int get_L()
{
    int x = 0;
    for(int i = 1;i <= l;i ++)
        x *= 26,x += L[i] - 'A',x %= M;
    return x % M;
}
void xfs()
{
    if(!get_L())
    {
        puts("0 0");
        exit(0);
    }
    for(int i = 1;i < l;i ++)
    {
        for(int j = i + 1;j <= l;j ++)
        {
            swap(L[i],L[j]);
            if(!get_L())
            {
                printf("%d %d\n",i,j);
                exit(0);
            }
            swap(L[i],L[j]);
        }
    }
    puts("-1 -1");
    return;
}
int main()
{
    scanf("%s %d",L + 1,&M);
    l = strlen(L+1);
    if(M == 26)
    {
        if(L[l] == 'A')
        {
            puts("0 0");
            return 0;
        }
        for(int i = 1;i <= l;i ++)
            if(L[i] == 'A')
            {
                printf("%d %d\n",i,l);
                return 0;
            }
        puts("-1 -1");
        return 0;
    }
    if(M == 5)
    {
        if(L[l] - 'A' % 5 == 0)
        {
            puts("0 0");
            return 0;
        }
        for(int i = 1;i <= l;i ++)
            if(L[i] - 'A' % 5 == 0)
            {
                printf("%d %d\n",i,l);
                return 0;
            }
        puts("-1 -1");
        return 0;
    }
    if(M == 25)
    {
        int ans1 = 10000,ans2 = 10000;
        if(L[l-1] - 'A' == 0 || L[l-1] - 'A' == 2 || L[l-1] - 'A' == 5 || L[l-1] - 'A' == 7)
            if(L[l] - 'A' == 5 || L - 'A' == 0)
            {
                puts("0 0");
                return 0;
            }

        if(L[l] - 'A' == 5 || L[l] - 'A' == 0)
        {
            for(int i = 1;i < l;i ++)
                if(L[i] - 'A' == 0 || L[i] - 'A' == 2 || L[i] - 'A' == 5 || L[i] - 'A' == 7)
                {
                    ans1 = i;
                    break;
                }
        }
        if(L[l-1] - 'A' == 0 || L[l-1] - 'A' == 2 || L[l-1] - 'A' == 5 || L[l-1] - 'A' == 7)
        {
            for(int i = 1;i < l-1;i ++)
                if(L[i] - 'A' == 0 || L[i] - 'A' == 5)
                {
                    ans2 = i;
                    break;
                }
        }
        if(ans1 < ans2)
        {
            printf("%d %d\n",ans1,l-1);
            return 0;
        }
        if(ans2 < ans1)
        {
            printf("%d %d\n",ans2,l);
            return 0;
        }
        puts("-1 -1");
        return 0;
    }
    xfs();
    return 0;
}

结果一个根本不对的东西在codevs上水了一大发……(85!!!)

关于100分算法
在不取模,十进制的时候,怎样交换第i位和第j位……?
设原数按位存在数组num里……为啥要这样存

x -= 10 ^ (i-1) * num[i];
x -= 10 ^ (j-1) * num[i];
x += 10 ^ (i-1) * num[j];
x += 10 ^ (j-1) * num[i];

然后,26进制可以类比
所以就解决啦……

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int MAXL = 2000 + 5;
char L[MAXL];
int M;
int l,k;
int v[MAXL];
void init()
{
    v[l] = 1;
    for(int i = l - 1;i > 0;i --)
    {
        v[i] = v[i + 1] * 26;
        v[i] %= M;
    }
    k = 0;
    for(int i = 1;i <= l;i ++)
        k *= 26,k += L[i] - 'A',k %= M;
    return;
}
int _swap_(int i,int j)
{
    int sum = k;
    sum -= (v[i] * (L[i] - 'A')) % M;
    sum -= (v[j] * (L[j] - 'A')) % M;
    sum += (v[i] * (L[j] - 'A')) % M;sum %= M;
    sum += (v[j] * (L[i] - 'A')) % M;sum %= M;
    return sum;
}
void xfs()
{
    if(k % M == 0)
    {
        puts("0 0");
        exit(0);
    }
    for(int i = 1;i < l;i ++)
        for(int j = i + 1;j <= l;j ++)
        {
            if(_swap_(i,j) % M == 0)
            {
                printf("%d %d\n",i,j);
                exit(0);
            }
        }
    puts("-1 -1");
    exit(0);
}
int main()
{
    scanf("%s %d",L + 1,&M);
    l = strlen(L + 1);
    init();
    xfs();
    return 0;
}

转载于:https://my.oschina.net/u/2992707/blog/778003

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值