zoukankan      html  css  js  c++  java
  • A

    论业界毒瘤之矩阵快速幂 + 快速乘。

    因为%数是1e13爆long long了所以要快速乘...不会O(1)的就写了个O(logn)的。

    这个溢出害我调了半天...

    【题目描述】

    斐波那契数列满足f[0]=0,f[1]=1,f[i]=f[i-1]+f[i-2](i>=2)。已知f[i]对1e13取模的结果k,求最小的可能的i。无解输出-1。

    【输入】

    输入包含一个非负整数k。

    【输出】

    输出一个整数,为最小的可能的i。无解输出-1。

    【输入样例】

    17711

    7

    【输出样例】

    22

    9366795780274 

    【提示】

    对于100%的数据点,0<=k<1e13。

    解:若 x % 1e13 == k 那么 x % d == k % d (d | 1e13)

    由这个性质我们可以十进制拆分。

    由于斐波那契数列数列的某个性质:对k取模时循环节不会超过6k

    我们搞了个循环节表出来:

    10 60

    100 300

    1000及以上  1500及以上

    这里是找循环节的代码。

     1 #include <cstdio>
     2 #include <vector>
     3 const int N = 1000010;
     4 std::vector<int> pos[N];
     5 int f[N];
     6 int main() {
     7     int n;
     8     scanf("%d", &n);
     9     f[0] = 0;
    10     f[1] = 1;
    11     pos[1].push_back(1);
    12     for(int i = 2; ; i++) {
    13         f[i] = (f[i - 1] + f[i - 2]) % n;
    14         for(int j = 0; j < pos[f[i]].size(); j++) {
    15             if(f[pos[f[i]][j] - 1] == f[i - 1]) {
    16                 printf("find:%d 
    ", i - pos[f[i]][j]);
    17                 return 0;
    18             }
    19         }
    20         pos[f[i]].push_back(i);
    21     }
    22     return 0;
    23 }
    View Code

    然后算法流程如下:

    找到60以内对10取模结果为k % 10的数。

    对每个数,在300范围内加60,判断是不是%100结果为k % 100

    对每个数,在1500内加300,判断%1000结果是不是k % 1000

    ...

    直到%1e13

    矩阵快速幂有剧毒...

      1 #include <cstdio>
      2 #include <algorithm>
      3 #include <vector>
      4 #include <cstring>
      5 typedef long long LL;
      6 const int N = 100010;
      7 
      8 inline LL m(LL a, LL b, LL p) {
      9     a %= p;
     10     b %= p;
     11     LL ans = 0;
     12     while(b) {
     13         if(b & 1) {
     14             ans = (ans + a) % p;
     15         }
     16         a = (a + a) % p;
     17         b = b >> 1;
     18     }
     19     return ans;
     20 }
     21 LL b[3][3], a[3][3], c[3][3], ans[3][3];
     22 inline void mulself(LL p) {
     23     memset(b, 0, sizeof(b));
     24     for(int i = 1; i <= 2; i++) {
     25         for(int j = 1; j <= 2; j++) {
     26             for(int k = 1; k <= 2; k++) {
     27                 b[i][j] += m(a[i][k], a[k][j], p) % p;
     28                 b[i][j] %= p;
     29             }
     30         }
     31     }
     32     std::swap(a, b);
     33     return;
     34 }
     35 
     36 inline void mula(LL p) {
     37     memset(b, 0, sizeof(b));
     38     for(int i = 1; i <= 2; i++) {
     39         for(int j = 1; j <= 2; j++) {
     40             for(int k = 1; k <= 2; k++) {
     41                 b[i][j] += m(ans[i][k], a[k][j], p) % p;
     42                 b[i][j] %= p;
     43             }
     44         }
     45     }
     46     std::swap(b, ans);
     47     return;
     48 }
     49 
     50 inline void mulc(LL p) {
     51     memset(b, 0, sizeof(b));
     52     for(int j = 1; j <= 2; j++) {
     53         for(int k = 1; k <= 2; k++) {
     54             b[1][j] += m(c[1][k], ans[k][j], p) % p;
     55             b[1][j] %= p;
     56         }
     57     }
     58     std::swap(b, c);
     59     return;
     60 }
     61 
     62 inline LL getsum(LL k, LL p) {
     63     if(k == 0) {
     64         return 0;
     65     }
     66     if(k == 1) {
     67         return 1;
     68     }
     69     k--;
     70     memset(a, 0, sizeof(a));
     71     memset(c, 0, sizeof(c));
     72     memset(ans, 0, sizeof(ans));
     73     a[1][2] = 1;
     74     a[2][1] = 1;
     75     a[2][2] = 1;
     76     ans[1][1] = 1;
     77     ans[2][2] = 1;
     78     c[1][2] = 1;
     79     while(k) {
     80         if(k & 1) {
     81             mula(p);
     82         }
     83         mulself(p);
     84         k = k >> 1;
     85     }
     86     mulc(p);
     87     return c[1][2];
     88 }
     89 
     90 
     91 std::vector<LL> v[2];
     92 LL d[20], po[20];
     93 
     94 int main() {
     95     /*for(int i = 1; i <= 66; i++) {
     96         printf("%d %lld 
    ", i, getsum(i, 100000000000000));
     97     }
     98     LL x;
     99     while(scanf("%lld", &x)) {
    100         printf("----%lld
    ", getsum(x, 10000000000));
    101     }*/
    102 
    103     LL k;
    104     scanf("%lld", &k);
    105     d[1] = 60;
    106     d[2] = 300;
    107     po[2] = 100;
    108     for(LL i = 3, t = 1000; i <= 15; i++, t = t * 10) {
    109         d[i] = t + (t >> 1);
    110         po[i] = t;
    111     }
    112 
    113     for(int i = 0; i <= 60; i++) {
    114         if(getsum(i, 10) == k % 10) {
    115             v[0].push_back(i);
    116             //printf("%dth 
    ", i);
    117         }
    118     }
    119     int p = 0;
    120 
    121     for(int i = 2; i <= 13; i++) {
    122         //printf("i = %d 
    ", i);
    123         p = p ^ 1;
    124         v[p].clear();
    125         for(int j = 0; j < v[!p].size(); j++) {
    126             for(LL g = v[!p][j]; g <= d[i]; g += d[i - 1]) {
    127                 //printf("%lld is find 
    ", g);
    128                 ///printf("%d == %d 
    ", getsum(g, po[i]), k % po[i]);
    129                 if(getsum(g, po[i]) == k % po[i]) {
    130                     //printf("%lld           pass 
    ", g);
    131                     v[p].push_back(g);
    132                 }
    133             }
    134         }
    135         if(!v[p].size()) {
    136             printf("-1");
    137             return 0;
    138         }
    139     }
    140 
    141     LL ans = 1ll << 62;
    142     for(int i = 0; i < v[p].size(); i++) {
    143         ans = std::min(ans, v[p][i]);
    144     }
    145     printf("%lld", ans);
    146     return 0;
    147 }
    AC代码

     

  • 相关阅读:
    hdu 3996
    poj 3189
    poj 2391
    zoj 3165
    【Visual Studio】
    httpwebrequest Winform 上传图片
    [MVC] win7 下 配置 IIS 问题
    win7 下 升级 vs2008
    [Visual Studio 2010] NET 4.0 WinForm无法引用System.Web.dll的解决方法
    [XML] XML
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/9397420.html
Copyright © 2011-2022 走看看