POJ3696

天大地大妈咪最大 提交于 2019-12-04 15:42:08

POJ3696POJ3696

  • 题目
    POJ3696
  • 题意
  • 分析
    xx88连在一起组成的正整数可写作8(10x1)9{\frac{8{(10^x-1)}}{9}},把题目的问题转化为:求一个最小的xx,满足L8(10x1)/9L|8(10^x-1)/9.
    • 前提:
      gcd(ac,bc)=cgcd(ac,bc) = c \Rightarrow gcd(a,b)=1gcd(a,b) = 1
      gcd(acgcd(ac,bc),bcgcd(ac,bc))=1gcd({\frac{ac}{gcd(ac,bc)}},{\frac{bc}{gcd(ac,bc)}}) = 1
      即:正整数x,yx,y的最大公约数不为11时,可以通过同时除以最大公约数方法使得这两个数互质。
      已知qpx,gcd(p,q)=1q|p*x,gcd(p,q) = 1 \Rightarrow qxq|x.
      推广式:
      dijd|i*j \Rightarrow dgcd(i,d)j{\frac{d}{gcd(i,d)}|{j}}
    • 推导:
      L8(10x1)99L8(10x1)L|{\frac{8(10^x-1)}{9}} {\Leftrightarrow} 9L|8(10^x-1)
      需要化简成:m10x1m|10^x-1这样的形式。88不能直接除到9L9L那里。所以先
      8(10x1)9=kL{\frac{8(10^x-1)}{9}} = kL
      \qquad\Downarrow
      8(10x1)=9kL8(10^x-1) = 9kL
      \qquad\Downarrow
      现在是9L8(10x1)9L|8(10^x-1) gcd(L,8)gcd(L,8)不一定等于11,所以需要等式两边同时除以gcd(8,L)gcd(8,L),使得满足等式两边gcdgcd等于11
      \qquad\Downarrow
      8(10x1)gcd(8,L)=9kLgcd(8,L){\frac{8(10^x-1)}{gcd(8,L)}} = {\frac{9kL}{gcd(8,L)}}
      p=8gcd(8,L),q=9Lgcd(8,L)p = {\frac{8}{gcd(8,L)}},q = {\frac{9L}{gcd(8,L)}}
      则:
      p(10x1)=qkp*(10^x-1) = qk
      由前提:q(10x1)q|(10^x-1)即:
      9Lgcd(L,8)(10x1){\frac{9L}{gcd(L,8)}}|(10^x-1)
      \qquad\Downarrow
      10x1(mod9Lgcd(L,8))10^x{\equiv}1{\pmod{\frac{9L}{gcd(L,8)}}} 同余性质
  • 代码
/*
独立思考
*/
#include <math.h>
#include <cstdio>
#include <iostream>
using namespace std;
template <typename T>
void read(T &x)
{
	x = 0;
	char c = getchar();
	int sgn = 1;
	while (c < '0' || c > '9') {if (c == '-')sgn = -1; c = getchar();}
	while (c >= '0' && c <= '9')x = x * 10 + c - '0', c = getchar();
	x *= sgn;
}
template <typename T>
void out(T x)
{
	if (x < 0) {putchar('-'); x = -x;}
	if (x >= 10)out(x / 10);
	putchar(x % 10 + '0');
}
typedef long long ll;
typedef unsigned long long ull;
ll d, k, p, s, L;
ll phi(ll n) {
	ll ans = n;
	for (int i = 2; i * i <= n; i++)
		if (n % i == 0) {
			ans = ans / i * (i - 1);
			while (n % i == 0) n /= i;
		}
	if (n > 1) ans = ans / n * (n - 1);
	return ans;
}

ll gcd(ll x, ll y) {
	return y ? gcd(y, x % y) : x;
}


ll ksc(ll a, ll b, ll c) {
	ll ans = 0;
	while (b) {
		if (b & 1) ans = (ans + a) % c;
		a = a * 2 % c;
		b >>= 1;
	}
	return ans;
}

ll ksm(ll a, ll b, ll c) {
	ll ans = 1 % c;
	a %= c;
	while (b) {
		if (b & 1) ans = ksc(ans, a, c);
		a = ksc(a, a, c);
		b >>= 1;
	}
	return ans;
}

ll number() {
	d = gcd(L, 8ll);
	k = 9 * L / d;
	if (gcd(k, 10ll) != 1) return 0;
	p = phi(k);
	s = sqrt(p);
	for (int i = 1; i <= s; i++)
		if (p % i == 0 && ksm(10ll, i, k) == 1)
			return i;
	for (int i = s - 1; i; i--)
		if (p % i == 0 && ksm(10ll, p / i, k) == 1)
			return p / i;
	return 0;
}


int main ()
{
	int flag = 0;
	while (scanf("%lld", &L) != EOF && L)
	{
		printf("Case %d: %lld\n", ++flag, number());
	}
	return 0 ;
}
  • 方法
    欧拉函数,同余,快速幂
  • 总结
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!