切糕(bzoj 3144)
Description
Input
第一行是三个正整数P,Q,R,表示切糕的长P、 宽Q、高R。第二行有一个非负整数D,表示光滑性要求。接下来是R个P行Q列的矩阵,第z个 矩阵的第x行第y列是v(x,y,z) (1≤x≤P, 1≤y≤Q, 1≤z≤R)。
100%的数据满足P,Q,R≤40,0≤D≤R,且给出的所有的不和谐值不超过1000。
Output
仅包含一个整数,表示在合法基础上最小的总不和谐值。
Sample Input
2 2 2
1
6 1
6 1
2 6
2 6
1
6 1
6 1
2 6
2 6
Sample Output
6
HINT
最佳切面的f为f(1,1)=f(2,1)=2,f(1,2)=f(2,2)=1
/* 个人感觉很神的一道题目。 如果有解的话,会有一个p满足:(10^x-1)/9*8=L*p => 10^x-1=9*L*p/8 设m=9*L/gcd(L,8) 则存在p1使得 10^x-1=m*p1 => 10^x=1(mod m) 根据欧拉定理 10^φ(m)=1(mod m) 所以x一定是φ(m)的因数(这好像是某个定理)。 */ #include<iostream> #include<cstdio> #define lon long long #define N 400010 #ifdef unix #define LL "%lld" #else #define LL "%I64d" #endif using namespace std; int prime[N],f[N],num,qlen; lon q[N]; void get_prime(){ for(int i=2;i<N;i++){ if(!f[i]) prime[++num]=i; for(int j=1;j<=num;j++){ if(i*prime[j]>=N) break; f[i*prime[j]]=1; if(i%prime[j]==0) break; } } } lon gcd(lon a,lon b){ if(!b) return a; return gcd(b,a%b); } lon euler(lon x){ lon res=x; for(lon i=2;i*i<=x;i++) if(x%i==0){ res-=res/i; while(x%i==0) x/=i; } if(x>1) res-=res/x; return res; } void get_q(lon n){ qlen=0; for(int i=1;i<=num&&n>1;i++){ while(n%(lon)prime[i]==0){ n/=prime[i]; q[++qlen]=prime[i]; } } if(n>1) q[++qlen]=n; } lon mul(lon a,lon b,lon mod){ lon base=a,r=0; while(b){ if(b&1) r+=base;r%=mod; base+=base;base%=mod; b>>=1; } return r; } lon poww(lon a,lon b,lon mod){ lon base=a,r=1; while(b){ if(b&1) r=mul(r,base,mod); base=mul(base,base,mod); b>>=1; } return r; } int main(){ int cas=0;lon L;get_prime(); while(scanf(LL,&L)&&L){ lon m=9*L/gcd(L,8); if(gcd(m,10)>1){ printf("Case %d: 0\n",++cas); continue; } lon x=euler(m);get_q(x); for(int i=1;i<=qlen;i++){ if(poww(10,x/q[i],m)==1){ x/=q[i]; } } printf("Case %d: ",++cas); printf(LL,x);printf("\n"); } return 0; }