1. 程式人生 > >POJ3708 Recurrent Function

POJ3708 Recurrent Function

線性方程組 -1 技術 lap 方程 [] amp fine display

【題意】

  給出一個正整數d(2<=d<=100);一個元素個數為d-1的集合a,每個集合元素ai對應一個1~d-1的整數;以及定義相同的大小為d集合bi。

  f函數的定義原題已給出。求數m最少經過多少次函數操作變為數k,無解輸出NO。

【題解】

  我們可發現當x>=d時,f(x)=d*f(x/d)+b[x mod d],x<d時,f(x)=a[x]。

  不難發現其實這就是在x的d進制下,對每一位進行變換,某一位如果是x,要麽變a[x],要麽變b[x]。所以答案就是當某一次操作後,每一位都與目標數一致。

  於是對m在d進制下的每一位找第一次到達目標數的次數以及循環節(之所以有a與b兩個集合就是防止最高位變為0)。最後就成了求n個模線性方程組求解的問題。

【代碼】

技術分享
  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <algorithm>
  5 #define ll long long
  6 using namespace std;
  7 struct node
  8 {
  9     ll a,r;
 10 }a[1000];
 11 int n,A[105],B[105],flag[105],po[1000],sum[1000],c[1000],d[1000];
 12 ll D;
 13 char st[105
]; 14 int read() 15 { 16 int x=0,sign=1;char ch; 17 do{ch=getchar();if(ch==-)sign=-sign;}while(ch<0||ch>9); 18 do{x=x*10+ch-48;ch=getchar();}while(ch>=0&&ch<=9); 19 return x*sign; 20 } 21 void exgcd (ll a,ll b,ll &x,ll &y) 22 { 23 if (b==0
) 24 { 25 D=a; 26 x=1; 27 y=0; 28 return; 29 } 30 exgcd(b,a%b,x,y); 31 ll t=x; 32 x=y; 33 y=t-a/b*y; 34 } 35 ll crt(node a[],int n) 36 { 37 for (int i=1;i<=n;++i) if (a[i].r==-1) return -1; 38 ll A=a[1].a,R=a[1].r,x,y,q; 39 for (int i=2;i<=n;++i) 40 { 41 exgcd(A,-a[i].a,x,y); 42 if ((a[i].r-R)%D)return -1; 43 q=-a[i].a/D; 44 x=(a[i].r-R)/D%q*x%q; 45 R=A*x+R; 46 A=q*A; 47 } 48 if (A<0) A=-A; 49 return (R%A+A)%A; 50 } 51 node rpt(int A[],int n,int x,int y) 52 { 53 int cnt=0; 54 for (int i=0;i<=n;++i) flag[i]=0; 55 while (!flag[x]) 56 flag[x]=++cnt,x=A[x]; 57 return {cnt,flag[y]-1}; 58 } 59 void div(int sum[],int d) 60 { 61 po[0]=0;int x=0; 62 for (int i=1;i<=sum[0];++i) 63 { 64 x=x*10+sum[i]; 65 if (!po[0] && x>=d || po[0]) 66 po[++po[0]]=x/d,x%=d; 67 } 68 sum[0]=po[0]; 69 for (int i=1;i<=po[0];++i) sum[i]=po[i]; 70 } 71 int mo(int sum[],int d) 72 { 73 int x=0; 74 for (int i=1;i<=sum[0];++i) 75 { 76 x=x*10+sum[i]; 77 if (x>=d) x=x%d; 78 } 79 return x; 80 } 81 void get(int c[],int d) 82 { 83 scanf("%s",st+1); 84 sum[0]=strlen(st+1); 85 for (int i=1;i<=sum[0];++i) 86 sum[i]=st[i]-48; 87 c[0]=0; 88 while (sum[0]) 89 { 90 c[++c[0]]=mo(sum,d); 91 div(sum,d); 92 } 93 for (int i=1;i+i<=c[0];++i) swap(c[i],c[c[0]-i+1]); 94 } 95 int main() 96 { 97 while (1) 98 { 99 n=read(); 100 if (n==-1) break; 101 for (int i=1;i<n;++i) A[i]=read(); 102 for (int i=0;i<n;++i) B[i]=read(); 103 get(c,n);get(d,n); 104 if (c[0]!=d[0]){puts("NO");continue;} 105 a[1]=rpt(A,n-1,c[1],d[1]); 106 for (int i=2;i<=c[0];++i) a[i]=rpt(B,n,c[i],d[i]); 107 ll ans=crt(a,c[0]); 108 if (ans==-1) puts("NO"); 109 else printf("%I64d\n",ans); 110 } 111 return 0; 112 }
View Code

  說實話寫的有點醜。。。。

POJ3708 Recurrent Function