poj 3708

原创 2015年07月07日 11:04:30

题目描述:

抽象一下就是:先给出一个100位的大整数.转换成d<100进制的数.然后有一个同样的目标数.d进制下位数要一样.每次转换i对应i位,最高位用a,低位用b.然后问最少转换几次能够到目标数.

题解:

第一步是高精度的进制转换.第二步是100个数,每个数求出来第一次转成功的次数,以及循环数(注意,感觉题目有毛病,其实就是第二次遇到目标数-第一次的次数就是循环数,竟然可能没有循环.标准的应该是随便找个循环就行).之后解线性同余模方程.

重点:

高精度转换+找循环和次数+线性同余模方程

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <ctype.h>
#include <limits.h>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <stack>
#include <set>
#include <bitset>
#define CLR(a) memset(a, 0, sizeof(a))
#define REP(i, a, b) for(ll i = a;i < b;i++)
#define REP_D(i, a, b) for(ll i = a;i <= b;i++)

typedef long long ll;

using namespace std;

struct P
{
    ll a, b;
};

const ll maxn = 100+10;
const ll eps = 5000;
ll res_m[maxn], res_k[maxn], ans[maxn], start[maxn];
char m[maxn], k[maxn];
ll d;
ll a[maxn], b[maxn];
ll vis[maxn], B[maxn], M[maxn];

ll gcd(ll a, ll b)
{
    if(b==0)
    {
        return a;
    }
    return gcd(b, a%b);
}
ll ext_gcd(ll a, ll b, ll &x, ll &y)
{
    if(b==0)
    {
        x = 1;
        y = 0;
        return a;
    }
    ll r = ext_gcd(b, a%b, x, y);
    ll t = x;
    x = y;
    y = t - (a/b*y);
    return r;
}

void trans(char s[], ll base1, ll base2, ll res[])//从高位开始除,答案保留在res中,并且是倒序
{
    //CLR(res);
    res[0] = 0;
    start[0] = strlen(s);
    REP(i, 0, start[0])
    {
        start[i+1] = s[i]-'0';
    }
    while(start[0] >= 1)
    {
        ll y = 0;
        ans[0] = start[0];
        REP_D(i, 1, start[0])
        {
            y = y*base1 + start[i];
            ans[i] = y/base2;
            y %= base2;
        }
        res[++res[0]] = y;
        ll i = 1;
        while(i <= ans[0]&&ans[i]==0)
        {
            i++;
        }
        start[0] = 0;
        while(i<=ans[0])
        {
            start[++start[0]] = ans[i];
            i++;
        }

    }
}

P mo_fangchengzu()//方程组
{
    ll x = 0, m=1;
    REP_D(i, 1, res_k[0])
    {
        ll a = m, b = ((B[i]-x)%M[i] + M[i])%M[i];
        ll d = gcd(a, M[i]);
        if(b%d!= 0)
        {
            return (P){0, -1};
        }
        else
        {
            ll t, temp;
            a /= d;
            b /= d;
            M[i] /= d;
            ext_gcd(a, M[i], t, temp);
            t = (t%M[i]+M[i])%M[i];
            t = (t*b)%M[i];
            x=x+m*t;
            m *= M[i];
            x %= m;
        }
    }
    return (P){x, m};
}

ll solve()//注意是ll...wa了好久这个地方
{
    trans(m, 10, d, res_m);
    trans(k, 10, d, res_k);
//    REP_D(i, 1, res_m[0])
//    {
//        prllf("%d ", res_m[i]);
//    }
//    prllf("\n");
    if(res_m[0]!=res_k[0])
    {
        return -1;
    }
    for(ll i = 1; i <= res_k[0]; i++)
    {
        //CLR(vis);
        ll from = res_m[i];
        ll to = res_k[i];
        //vis[from]=1;
        ll now = from;
        ll cnt = 0;
        ll ans = -1;
        while(1)
        {
            if(now == to&&ans==-1)//找循环
            {
                ans = cnt;
            }
            else if(now==to)
            {
                M[i] = cnt - ans;
                break;
            }

            //vis[now] = 1;
            cnt++;
            if(cnt > eps)
                return -1;
            if(i != res_k[0])
                now = b[now];
            else
                now = a[now];
        }
        //M[i] = cnt;
        if(ans==-1)
        {
            return -1;
        }
        B[i] = ans;
    }
    P out = mo_fangchengzu();
    if(out.b==-1)
    {
        return -1;
    }
    return out.a;
}


int main()
{
    //freopen("4Din.txt", "r", stdin);
    //freopen("4Dout.txt", "w", stdout);
    while(scanf("%I64d", &d) && d != -1)
    {
        REP_D(i, 1, d - 1)
        {
            scanf("%I64d", &a[i]);
        }
        REP_D(i, 0, d - 1)
        {
            scanf("%I64d", &b[i]);
        }
        scanf("%s%s", m, k);
        ll t = solve();
        if(t==-1)
        {
            printf("NO\n");
        }
        else
        {
            printf("%I64d\n", t);
        }
    }
    return 0;
}

POJ 3708 高精度 + 置换 + 中国剩余定理

传送门:POJ 3708题解(1)设m, k的d进制表示分别为p1p2···pn1, k1k2···kn2 其中n1, n2是位数(2)由f(m)f(m)定义得: f(m)=ap1∗dn−1...
  • ADjky
  • ADjky
  • 2017年03月06日 17:14
  • 371

【贪心】【POJ3154】墓地雕塑(Graveyard, NEERC 2006, LA 3708)需要稍稍加工的(先贪心,再确保能这样贪(可行性&&如果可行必定最优&&非证明最优性)的题)(K)

例题4  墓地雕塑(Graveyard, NEERC 2006, LA 3708) 在一个周长为10000的圆上等距分布着n个雕塑。现在又有m个新雕塑加入(位置可以随意放),希望所有n+m个...

UVAlive3708 UVA1388 POJ3154 Graveyard【水题】

Graveyard Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 1715   Acce...

【思维】POJ3154 LA3708Graveyard NEERC2006

题目链接 题目描述:在一个周长为10000的圆上,均匀放置nn个雕塑。现要添加mm个雕塑,使得这n+mn+m个雕塑均匀分布。求这nn个雕塑移动的总距离。看看样例说明,感觉有一个雕塑木有移动。接下来证...
  • cqbztsy
  • cqbztsy
  • 2015年08月13日 08:32
  • 363

zoj 3708 Density of Power Network

Density of Power Network Time Limit: 2 Seconds      Memory Limit: 65536 KB The vast power s...

zoj 3708 Density of Power Network(数学啊)

zoj 3708 Density of Power Network(数学啊)

UVALive 3708_Graveyard

题目描述: 有个1000步距离的圆环,环上的两点之间的距离是一样的,及环上的点平分周长。题目给出初始点个数和将要加上点的个数,把初始的点调整下位置,然后把要加入点的接上,求总调整距离的最小值。 解题方...

墓碑移动 LA3708(圆上点的移动)

在一个周长为 10000 的圆上等距分布着 n 个雕塑。现在又有 m 个新雕塑加入(位置可以随意摆放),希望所有 n + m 个雕塑能在圆周上均匀分布。这就需要移动一些原有的雕塑。要求 n 个雕塑...

UVaLive 3708 Graveyard (构造法求解最优化问题)

来源:《算法竞赛入门经典训练指南》第1章例题4、UVaLive 3708、POJ3154 这里只给出确实有一个最优解,其中必定有一个墓碑不动.至于其他的内容,网上茫茫多的解释我也想不出什么更有新意...

ZOJ 3708 Density of Power Network

Description The vast power system is the most complicated man-made system and the greatest engine...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:poj 3708
举报原因:
原因补充:

(最多只允许输入30个字)