牛客國慶集訓派對Day1 C Utawarerumono(暴力)
阿新 • • 發佈:2018-11-19
題意:
關於變數x,y的不定方程ax+by=c,顯然這個方程可能有多個整數解。Kuon想知道如果有解,使得p2*x2+p1*x+q2*y2+q1*y最小的一組整數解是什麼。為了方便,你只需要輸出p2*x2+p1*x+q2*y2+q1*y的最小值。
如果方程無整數解,輸出“Kuon”。如果有整數解,輸出p2*x2+p1*x+q2*y2+q1*y的最小值。
解析:
這道題我真的不想說什麼.....資料水的要死,但是卡了我一天...
最後發現是ll 轉換成 double 運算然後再轉回 ll 出現了問題.....
我的思路就是把y用x代替,然後變成一個一元二次方程,然後按照x=-a/2b,求最值就可以了
官方題解使用暴力取列舉x,然後分別帶入原來的式子求最值的,但暴力的範圍是[-1e5,1e5]這個我搞不懂怎麼來的,
可能按照資料大小猜的把...
最後就是這道題,a=0&b=0&c=0,a&!b,!a&b的資料都沒有,我看過的程式碼,這裡的特判輸出什麼的都有..
按我的理解a=0的話,那麼x的範圍就是[-INF,INF],並且不受y影響,那麼就直接取p2*x2+p1*x的最小值就可以了,b=0同理
暴力列舉的方法
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int MAXN = 1e5+10; const ll INF = 0x3f3f3f3f3f3f3f3f; ll s1,s2,s3; ll gcd(ll a,ll b) { ll tmp; while(b) { tmp=a%b; a=b; b=tmp; } return a; } ll a,b,c,yu; ll p1,p2,q1,q2; inline ll cal(ll x) { ll y=(c-a*x)/b; return p2*x*x+p1*x+q2*y*y+q1*y; } inline ll calzz(ll p,ll q,ll x) { return p*x*x+q*x; } inline ll solvezz(ll p2,ll p1) { ll ne; ll ans1=INF; ne=-p1/(2*p2); ans1=min(ans1,calzz(p2,p1,ne-1)); ans1=min(ans1,calzz(p2,p1,ne)); ans1=min(ans1,calzz(p2,p1,ne+1)); ans1=min(ans1,calzz(p2,p1,ne+2)); return ans1; } int main() { scanf("%lld%lld%lld",&a,&b,&c); scanf("%lld%lld",&p1,&p2); scanf("%lld%lld",&q1,&q2); if(a==0&&b==0) { if(c) printf("Kuon\n"); else { printf("%lld\n",solvezz(p2,p1)+solvezz(q2,q1)); } return 0; } ll g=gcd(a,b); if(c%g!=0) { printf("Kuon\n"); return 0; } a=a/g; b=b/g; c=c/g; ll ans; if(b==0) { ll x=c/a; ans=p2*x*x+p1*x+solvezz(q2,q1); printf("%lld\n",ans); return 0; } if(a==0) { ll x=c/b; ans=q2*x*x+q1*x+solvezz(p2,p1); printf("%lld\n",ans); return 0; } ans=INF; for(ll i=-100000;i<=100000;i++) { if((c-a*i)%b==0) { ans=min(ans,cal(i)); } } printf("%lld\n",ans); }
二元一次方程求解
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int MAXN = 1e5+10; const ll INF = 0x3f3f3f3f3f3f3f3f; ll s1,s2,s3; ll gcd(ll a,ll b) { ll tmp; while(b) { tmp=a%b; a=b; b=tmp; } return a; } ll a,b,c,yu; ll p1,p2,q1,q2; inline ll cal(ll x) { ll y=(c-a*x)/b; return p2*x*x+p1*x+q2*y*y+q1*y; } inline ll solve(ll stx) { ll ans=INF; ll w=(stx%b+b)%b; //ll mm=findstx(stx); ll mm=stx+(yu-w); ans=min(ans,cal(mm)); ans=min(ans,cal(mm-b)); ans=min(ans,cal(mm-b-b)); ans=min(ans,cal(mm-b-b-b)); ans=min(ans,cal(mm+b)); ans=min(ans,cal(mm+b+b)); ans=min(ans,cal(mm+b+b+b)); return ans; } inline void findyu() { for(ll i=0;i<b;i++) { if(((c-a*i)%b+b)%b==0) { yu=i; return; } } } inline ll calzz(ll p,ll q,ll x) { return p*x*x+q*x; } inline ll solvezz(ll p2,ll p1) { ll ne; ll ans1=INF; ne=-p1/(2*p2); ans1=min(ans1,calzz(p2,p1,ne-1)); ans1=min(ans1,calzz(p2,p1,ne)); ans1=min(ans1,calzz(p2,p1,ne+1)); ans1=min(ans1,calzz(p2,p1,ne+2)); return ans1; } int main() { scanf("%lld%lld%lld",&a,&b,&c); scanf("%lld%lld",&p1,&p2); scanf("%lld%lld",&q1,&q2); if(a==0&&b==0) { if(c) printf("Kuon\n"); else { printf("%lld\n",solvezz(p2,p1)+solvezz(q2,q1)); //printf("0\n"); } return 0; } ll g=gcd(a,b); if(c%g!=0) { printf("Kuon\n"); return 0; } a=a/g; b=b/g; c=c/g; ll ans; if(b==0) { ll x=c/a; ans=p2*x*x+p1*x+solvezz(q2,q1); printf("%lld\n",ans); return 0; } if(a==0) { ll x=c/b; ans=q2*x*x+q1*x+solvezz(p2,p1); printf("%lld\n",ans); return 0; } s1=p2*b*b+q2*a*a; s2=p1*b*b-2*a*c*q2-q1*a*b; s3=q2*c*c+q1*c*b; ll stx=-s2/(2*s1); /*yu=b-c%b; if(abs(c-a*yu)%b!=0) { yu=c%b; }*/ findyu(); ans=solve(stx); ans=min(ans,solve(stx+1)); ans=min(ans,solve(stx-1)); printf("%lld\n",ans); }