UVa 11490 Just Another Problem

方法:数学 整除

根据推导发现新的方阵长为2*x+3*d, 宽为 x+2*d, 面积满足方程 (2*x+3*d)*(x+2*d) = S + 2*x*x。 (d为thickness)

(比较合理的方法)

继而得到 x = (S-6*d*d)/(7*d) 枚举d即可。

code:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <bitset>
#include <cstdlib>
#include <cmath>
#include <set>
#include <list>
#include <deque>
#include <map>
#include <queue>
#include <fstream>
#include <cassert>
#include <unordered_map>
#include <cmath>
#include <sstream>
#include <time.h>
#include <complex>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
#define FOR(a,b,c) for (int (a)=(b);(a)<(c);++(a))
#define FORN(a,b,c) for (int (a)=(b);(a)<=(c);++(a))
#define DFOR(a,b,c) for (int (a)=(b);(a)>=(c);--(a))
#define FORSQ(a,b,c) for (int (a)=(b);(a)*(a)<=(c);++(a))
#define FORC(a,b,c) for (char (a)=(b);(a)<=(c);++(a))
#define FOREACH(a,b) for (auto &(a) : (b))
#define rep(i,n) FOR(i,0,n)
#define repn(i,n) FORN(i,1,n)
#define drep(i,n) DFOR(i,n-1,0)
#define drepn(i,n) DFOR(i,n,1)
#define MAX(a,b) a = Max(a,b)
#define MIN(a,b) a = Min(a,b)
#define SQR(x) ((LL)(x) * (x))
#define Reset(a,b) memset(a,b,sizeof(a))
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define all(v) v.begin(),v.end()
#define ALLA(arr,sz) arr,arr+sz
#define SIZE(v) (int)v.size()
#define SORT(v) sort(all(v))
#define REVERSE(v) reverse(ALL(v))
#define SORTA(arr,sz) sort(ALLA(arr,sz))
#define REVERSEA(arr,sz) reverse(ALLA(arr,sz))
#define PERMUTE next_permutation
#define TC(t) while(t--)
#define forever for(;;)
#define PINF 1000000000000
#define newline ‘\n‘

#define test if(1)if(0)cerr
using namespace std;
  using namespace std;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef pair<int,int> ii;
typedef pair<double,double> dd;
typedef pair<char,char> cc;
typedef vector<ii> vii;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> l4;
const double pi = acos(-1.0);

const int mod = 100000007;
const string str = "Possible Missing Soldiers = ", no = "No Solution Possible";

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    ll s;
    while (cin >> s && s)
    {
        vector<ll> ans;
        for (ll d = 1; d*d*6 < s; ++d)
        {
            ll x = s - 6*d*d;
            if (x % (7*d)) continue;
            x /= 7*d;
            ans.pb((x%mod)*(x%mod)*2%mod);
        }
        if (ans.size() == 0)
            cout << no << newline;
        else
        {
            rep(i, ans.size())
            cout << str << ans[i] << newline;
        }
        cout << newline;
    }
}

  

(我的傻方法)

利用求根公式,得到d的解为((49*x*x+24*S)^0.5 - 7*x)/12。

可以观察到,当x足够大时,49*x*x+24*S 无法构成一个平方数((7*x+1)^2 - (7*x)^2 = 14*x, 相邻的两个平方数的距离是不断增加的,当14*x > 24*S且S大于0时,49*x*x+24*S 不可能使平方数)。

所以 设 (7*x + a) = (49*x*x+24*S)^0.5, 枚举a。 注意 (7x+a)^2 - (7*x)^2 = a * (14x+a) = 24*S。 所以 a*a < 24*S, a < (24*S)^0.5 < 5e6, 可以接受。然后可以发现,d的解为((49*x*x+24*S)^0.5 - 7*x)/12 = (7*x+a - 7*x)/12 = a/12, 枚举 a的时候可以只枚举大于零 12的倍数,枚举的数量不超过 5e6/12, 对于1e3个testcase,时效足够了。

code:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <bitset>
#include <cstdlib>
#include <cmath>
#include <set>
#include <list>
#include <deque>
#include <map>
#include <queue>
#include <fstream>
#include <cassert>
#include <unordered_map>
#include <cmath>
#include <sstream>
#include <time.h>
#include <complex>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
#define FOR(a,b,c) for (int (a)=(b);(a)<(c);++(a))
#define FORN(a,b,c) for (int (a)=(b);(a)<=(c);++(a))
#define DFOR(a,b,c) for (int (a)=(b);(a)>=(c);--(a))
#define FORSQ(a,b,c) for (int (a)=(b);(a)*(a)<=(c);++(a))
#define FORC(a,b,c) for (char (a)=(b);(a)<=(c);++(a))
#define FOREACH(a,b) for (auto &(a) : (b))
#define rep(i,n) FOR(i,0,n)
#define repn(i,n) FORN(i,1,n)
#define drep(i,n) DFOR(i,n-1,0)
#define drepn(i,n) DFOR(i,n,1)
#define MAX(a,b) a = Max(a,b)
#define MIN(a,b) a = Min(a,b)
#define SQR(x) ((LL)(x) * (x))
#define Reset(a,b) memset(a,b,sizeof(a))
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define all(v) v.begin(),v.end()
#define ALLA(arr,sz) arr,arr+sz
#define SIZE(v) (int)v.size()
#define SORT(v) sort(all(v))
#define REVERSE(v) reverse(ALL(v))
#define SORTA(arr,sz) sort(ALLA(arr,sz))
#define REVERSEA(arr,sz) reverse(ALLA(arr,sz))
#define PERMUTE next_permutation
#define TC(t) while(t--)
#define forever for(;;)
#define PINF 1000000000000
#define newline ‘\n‘

#define test if(1)if(0)cerr
using namespace std;
  using namespace std;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef pair<int,int> ii;
typedef pair<double,double> dd;
typedef pair<char,char> cc;
typedef vector<ii> vii;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> l4;
const double pi = acos(-1.0);

const int mod = 100000007;
const string str = "Possible Missing Soldiers = ", no = "No Solution Possible";

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    ll s;
    while (cin >> s && s)
    {
        vector<ll> ans;
        ll bound = sqrt(24*s+0.5);
        for (ll a = 12; a <= bound; a += 12)
        {
            if (24*s%a != 0) continue;
            ll x = 24*s/a-a;
            if (x % 14 != 0) continue;
            x /= 14;
            if (x == 0) continue;
            ans.pb((x%mod)*(x%mod)*2%mod);
        }
        if (ans.size() == 0)
            cout << no << newline;
        else
        {
            rep(i, ans.size())
            cout << str << ans[i] << newline;
        }
        cout << newline;
    }
}

  

时间: 2024-10-20 08:06:49

UVa 11490 Just Another Problem的相关文章

uva 11490 - Just Another Problem(数学)

题目链接:uva 11490 - Just Another Problem 题目大意:有n个士兵,要排列成一个方阵,要求方阵尽量大,于是在方正的中间会空出两个正方形的区域,空出来的局域要求厚度相同,即正方形的四条边向相应方向均再有x行或者列. 解题思路:根据题意可以知道x(6x+7r)=n,x为厚度,r为正方形的边长.接着枚举x,x是n的因子. #include <cstdio> #include <cstring> #include <cmath> typedef l

UVA 11490 - Just Another Problem(数论)

11490 - Just Another Problem 题目链接 题意:有S个士兵,排成一个矩阵,矩阵中可以有两个洞,要求两个洞上下左右厚度一样,问能缺少士兵的情况数. 思路:推推公式,设厚度为a, 正方形为i, 那么(3 a + 2 i) (2 a + i) = S + 2 i i; 化简一下得到6 i i + 7 a i = S 由于S很大,所以去枚举厚度,这样只要枚举到sqrt(S)就够了,复杂度可以接受 代码: #include <stdio.h> #include <stri

UVA - 11490 Just Another Problem (因数分解)

There is a wise saying "Nothingis unfair in love and war". Probably that is why emperors of ancient days usedto use many funny and clever tricks to fool the opponents. The most commontechnique was to scare the opponent away by out numbering them

[2016-02-19][UVA][524][Prime Ring Problem]

UVA - 524 Prime Ring Problem Time Limit: 3000MS Memory Limit: Unknown 64bit IO Format: %lld & %llu Submit Status Description A ring is composed of n (even number) circles as shown in diagram. Put natural numbers  into each circle separately, and the

UVA 10837 - A Research Problem(欧拉函数)

UVA 10837 - A Research Problem 题目链接 题意:给定phi(n),求最小满足的最小的n 思路:phi(n)=pk11(p1?1)?pk22(p2?1)?pk33(p3?1)....(p为质数),因此对于给定phi(n),先把满足条件phi(n)%(p?1)=0的素数全找出来,在这些素数基础上进行暴力搜索,枚举哪些素数用与不用,求出最小值.这样做看似时间复杂度很高,但是实际上,由于每次多选一个素数之后对于值是呈指数上升的,所以实际组合出来的情况并不会太多,因此是可行的

uva 10401 Injured Queen Problem(DP)

uva 10401 Injured Queen Problem 题目大意:这是一个变形的N皇后问题,皇后不再是占据一行一列以及斜线,她占据的只是她周围的一圈以及她所在的一列.题目给出一个含有问号,数字和字母的字符串.第i个字符是问号代表皇后在第i列的任意一行,若第i个字符是数字或字母X(1-F)代表皇后在第i列的X行.求满足该字符串的摆放方式的方法一共有几种. 解题思路:从第一列开始往后递推.dp[i][j]表示的是结合j - 1列的摆放方式,将皇后放在(i, j)的位置会有几种情况. #inc

uva 10837 - A Research Problem(欧拉函数+暴力)

题目链接:uva 10837 - A Research Problem 题目大意:给定一个phin,要求一个最小的n,欧拉函数n等于phin 解题思路:欧拉函数性质有,p为素数的话有phip=p?1;如果p和q互质的话有phip?q=phip?phiq 然后根据这样的性质,n=pk11(p1?1)?pk22(p2?1)???pkii(pi?1),将所有的pi处理出来,暴力搜索维护最小值,虽然看上去复杂度非常高,但是因为对于垒乘来说,增长非常快,所以搜索范围大大被缩小了. #include <cs

UVA 1363 Joseph&#39;s Problem

https://vjudge.net/problem/UVA-1363 n 题意:求 Σ  k%i i=1 除法分块 如果 k/i==k/(i+1)=p 那么 k%(i+1)=k-(i+1)*p= k-i*p-p = k%i-p 所以 商相同时,余数为等差数列 我不知道为什么交到vjudge一直WA,网上搜的题解交上去也WA #include<cmath> #include<cstdio> using namespace std; int main() { int n,k,i,j,

uva 10026 Shoemaker&#39;s Problem(贪心+排序)

虽然是个水题,但是在一些细节上wa了几次,好像不支持'\b'退格符号,我用在了输出空格那,结果wa了...白白 wa了几次...题意是看的题解..今天只写了两道题,速度有点慢,得加快了,以后得先认真读懂题目,题目读懂了 就相当于做出来一半然后仔细动脑想想,有想法了再敲,不能盲目的做题.另外,热烈祝贺今天c++ primer看到 了100页 思路: 这道题是让给的数据是每件工作需要做的天数和每耽误一天所需要的费用,让求一个序列使得付费最小,如果有相同答 案把字典树最小的输出...输出的是序号,该件