• BZOJ1406: [AHOI2007]密码箱 数论


    Description

    在一次偶然的情况下,小可可得到了一个密码箱,听说里面藏着一份古代流传下来的藏宝图,只要能破解密码就能打开箱子,而箱子背面刻着的古代图标,就是对密码的提示。经过艰苦的破译,小可可发现,这些图标表示一个数以及这个数与密码的关系。假设这个数是n,密码为x,那么可以得到如下表述: 密码x大于等于0,且小于n,而x的平方除以n,得到的余数为1。 小可可知道满足上述条件的x可能不止一个,所以一定要把所有满足条件的x计算出来,密码肯定就在其中。计算的过程是很艰苦的,你能否编写一个程序来帮助小可可呢?(题中x,n均为正整数)

    Input

    输入文件只有一行,且只有一个数字n(1<=n<=2,000,000,000)。

    Output

    你的程序需要找到所有满足前面所描述条件的x,如果不存在这样的x,你的程序只需输出一行“None”(引号不输出),否则请按照从小到大的顺序输出这些x,每行一个数。

    Sample Input

    12

    Sample Output

    1
    5
    7
    11

    Solution

    首先考虑怎么去掉这个mod

    $$x^2 mod n = 1 $$

    可以化为

    $$kn=x^2-1$$

    $$kn=(x+1)(x-1)$$

    即$$n|(x+1)(x-1)$$

    所以枚举$n$的因数来算就好,注意要枚举大因数,小因数TLE的很惨...

    可以拿set来存答案也可以最后把答案排序一遍

    #include <bits/stdc++.h>
    
    #define ll long long
    #define inf 0x3f3f3f3f
    #define il inline
    
    namespace io {
    
        #define in(a) a=read()
        #define out(a) write(a)
        #define outn(a) out(a),putchar('
    ')
    
        #define I_int ll
        inline I_int read() {
            I_int x = 0 , f = 1 ; char c = getchar() ;
            while( c < '0' || c > '9' ) { if( c == '-' ) f = -1 ; c = getchar() ; }
            while( c >= '0' && c <= '9' ) { x = x * 10 + c - '0' ; c = getchar() ; }
            return x * f ;
        }
        char F[ 200 ] ;
        inline void write( I_int x ) {
            I_int tmp = x > 0 ? x : -x ;
            if( x < 0 ) putchar( '-' ) ;
            int cnt = 0 ;
            while( tmp > 0 ) {
                F[ cnt ++ ] = tmp % 10 + '0' ;
                tmp /= 10 ;
            }
            while( cnt > 0 ) putchar( F[ -- cnt ] ) ;
        }
        #undef I_int
    
    }
    using namespace io ;
    
    using namespace std ;
    
    #define N 100010
    
    //x^2 mod n = 1
    //kn = x^2 - 1 
    //n | x^2 - 1
    //n | (x+1)(x-1) 
    
    ll n = read() ; 
    ll st[ N ] ;
    int top = 0 ;
    int cnt[ N ] ;
    
    int main() {
        for( ll i = 1 ; i * i <= n ; i ++ ) {
            if( n % i == 0 ) {
                st[ ++ top ] = n / i ;
            }
        }
        int tot = 0 ;
        while( top ) {
            ll tmp = st[ top ] ;
            for( ; tmp <= n ; tmp += st[ top ] ) {
                if( ( tmp - 2 ) % ( n / st[ top ] ) == 0 ) 
                    cnt[ ++ tot ] = ( tmp - 1 ) % n ;
                if( ( tmp + 2 ) % ( n / st[ top ] ) == 0 ) 
                    cnt[ ++ tot ] = ( tmp + 1 ) % n ;
            }
            top -- ;
        }
        if( !tot ) puts("None") ;
        else {
            sort( cnt + 1 , cnt + tot + 1 ) ;
            for( int i = 1 ; i <= tot ; i ++ ) {
                if( cnt[ i ] != cnt[ i - 1 ] ) outn( cnt[ i ] ) ;
            }
        }
        return 0 ;
    }
  • 相关阅读:
    程序集、属性和元数据
    wget 使用探索
    为wget使用代理
    创建项目 (Visual C#)
    wget 下载整个网站,或者特定目录
    演练:使用 Visual C# 创作用户控件
    NavigateUrl属性绑定 天高地厚
    【转载】Repeater控件里的大智慧 天高地厚
    【转载】ASP.NET Page 那点事 天高地厚
    意向锁如何提高性能 天高地厚
  • 原文地址:https://www.cnblogs.com/henry-1202/p/BZOJ1406.html
Copyright © 2020-2023  润新知