切糕(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

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;
}

 

posted @ 2017-03-07 22:27  karles~  阅读(235)  评论(0编辑  收藏  举报