3.【HZOJ普及模拟2】
\(\Huge{打了一场模拟赛,又垫底了。qwq}\)
\(\Huge 快\)\(\Huge V\)\(\Huge 本\)\(\Huge 蒟\)\(\Huge 蒻\)\(\Huge 5\)\(\Huge 0\)
\(\huge 好的我们步入正题\)
\(\huge (逃)\)
HZOJ普及模拟2
T1 地址
\(20pts\)
- 本来挺水的一道题,结果硬生生丢了 \(80\) 分。。。 因为本蒟蒻在判断是否为数字时,如果是数字,则 \(continue\) 不再进行下面的计算,于是当最后一次循环时,如果还是数字,就 \(continue\) 了,于是
快乐的 \(WA\) 了 \(qwq\)。
//码风怪异
#include<iostream>
#include<cstring>
#include<string.h>
using std::string;
string a,b;
int num[10];
signed main(void)
{
//freopen("ip.in","r",stdin);
//freopen("ip.out","w",stdout);
int i,j,n,sum=0,flag=0;
std::cin>>a;
n=a.size();
int cnt=0;
for(i=0;i<n;++i)
{
if(a[i]>='0'&&a[i]<='9')
{
b[++cnt]=a[i];if(i!=n-1)continue;
}
else if(!flag)printf("NO\n"),flag=1;
if(cnt>3)
{
if(!flag)printf("NO\n"),flag=1;
++sum;
num[sum]=255;
cnt=0;
}
if(cnt<=3&&cnt!=0)
{
++sum;
for(j=1;j<=cnt;++j)
num[sum]=num[sum]*10+(b[j]-48);
if(num[sum]>255&&!flag)
printf("NO\n"),flag=1;
cnt=0;
}
}
if(!flag)
{printf("YES\n");return 0;}
for(i=1;i<=4;++i)
{
if(num[i]<=255)printf("%d",num[i]);
else printf("255");
if(i<4)printf(".");
}
}
T2 内积
\(60pts\)
- 本来也可以 \(A\) 掉的,但是一开始没有用 \(freopen\) 于是只得了 \(60\) 得 \(60\) 的原因是用了一个 \(int256\) 然后 \(T\) 了4个点,如果用 \(long long\) 就 \(AC\) 了。
- 本题是一个简单的贪心,我一开始想到了火柴排队,将两个数组从小到大(
或从大到小)排序一遍,然后for循环一次,用一个变量 \(sum\) (当然也可以不叫sum) - 如果 \(\Large{a_2 > a_1}\), \(\Large{b_2 > b_1}\) 那么 \(\Large{a_2b_2 > a_1b_2 , a_2b_1} > a_1b_1\) 。 \((\Large{a_1 , a_2 , b_1 , b_2 > 0})\) 。
- 证明:因为 \(\Large{a_2 - a_1 > 0}\) , \(\Large{b_2 - b_1 > 0}\) 所以 \(\Large{(a_2 - a_1)\times(b_2 - b_1) > 0}\) 。展开后得到 \(\Large{a_2b_2 - a_1b_2 - a_2b_1 + a_1b_1 > 0}\) ,因此 \(\Large{a_2b_2 + a_1b_1 > a_1b_2 + a_2b_1}\) \((\Large{a_1 , a_2 , b_1 , b_2 > 0})\)。
- 所以只要使得数组是有序的 (
从大到小或从小到大排序) ,就可以找到乘积的最大值
\(60pts\) 代码( \(TLE\)) \((int256)\)
- (觉得代码很长?点击右上角折叠)
//1145141919810......
#include <iostream>
#include <string>
#include <algorithm>
#include <stdexcept>
#include <cmath>
#include <cstring>
using namespace std;
#define MAXN 200001
double ax[MAXN], ay[MAXN], bx[MAXN], by[MAXN];
char sa[MAXN/2],sb[MAXN/2];
int sum[MAXN];
int x1[MAXN],x2[MAXN];
class int256 {
public:
std::string number;
bool negative;
int256() : number("0"), negative(false) {}
int256(const std::string& value) : number(value), negative(false) {
if (!value.empty() && value[0] == '-') {
negative = true;
number = number.substr(1);
}
}
friend std::ostream& operator<<(std::ostream& os, const int256& num) {
if (num.number == "0") {
os << "0";
} else {
if (num.negative) {
os << "-";
}
os << num.number;
}
return os;
}
friend std::istream& operator>>(std::istream& is, int256& obj) {
std::string input;
is >> input;
obj = int256(input);
return is;
}
int256 operator-() const {
return int256(number);
}
bool operator==(const int256& other)const{
return(number==other.number&&negative==other.negative);
}
bool operator<(const int256& other)const{
if(negative&&!other.negative)return 1;
else if(!negative&&other.negative)return 0;
else if(!negative&&!other.negative)
{
if(number.size()<other.number.size())return 1;
else if(number.size()>other.number.size())return 0;
else return number<other.number;
}
else return (-other)<(-(*this));
}
bool operator<=(const int256& other) const
{
if(number==other.number&&negative==other.negative)return 1;
if(negative&&!other.negative)return 1;
else if(!negative&&other.negative)return 0;
else if(!negative&&!other.negative)
{
if(number.size()<other.number.size())return 1;
else if(number.size()>other.number.size())return 0;
else return number<other.number;
}
else return (-other)<(-(*this));
}
bool operator>(const int256& other) const
{
if(negative&&!other.negative)return 0;
else if(!negative&&other.negative)return 1;
else if(!negative&&!other.negative)
{
if(number.size()<other.number.size())return 0;
else if(number.size()>other.number.size())return 1;
else return number>other.number;
}
else return (-(*this))<(-other);
}
bool operator>=(const int256& other) const
{
if(number==other.number&&negative==other.negative)return 1;
if(negative&&!other.negative)return 0;
else if(!negative&&other.negative)return 1;
else if(!negative&&!other.negative)
{
if(number.size()<other.number.size())return 0;
else if(number.size()>other.number.size())return 1;
else return number>other.number;
}
else return (-(*this))<(-other);
}
bool operator!=(const int256& other) const
{
return !(number==other.number);
}
int256 operator+(const int256& other) const {
int256 result;
if (negative == other.negative) {
result.number = aresult(number, other.number);
result.negative = negative;
} else {
if (abs_compare(number, other.number) >= 0) {
result.number = subtract(number, other.number);
result.negative = negative;
} else {
result.number = subtract(other.number, number);
result.negative = other.negative;
}
}
return result;
}
int256 operator++(int) const {
int256 res;
res.number='1';res.negative=0;
return *this+res;
}
int256 operator-(const int256& other) const {
int256 result;
if (negative != other.negative) {
result.number = aresult(number, other.number);
result.negative = negative;
} else {
if (abs_compare(number, other.number) >= 0) {
result.number = subtract(number, other.number);
result.negative = negative;
} else {
result.number = subtract(other.number, number);
result.negative = !negative;
}
}
return result;
}
int256 operator*(const int256& other) {
int256 result;
result.number = multiply(number, other.number);
result.negative = negative != other.negative;
return result;
}
int256 operator/(const int256& other) const {
if (other.number == "0") {
throw std::runtime_error("Division by zero");
}
int256 result;
result.number = divide(number, other.number);
result.negative = negative != other.negative;
return result;
}
int256 operator%(const int256& other) const {
if (other.number == "0") {
throw std::runtime_error("Division by zero");
}
int256 result;
result.number=divide(number,other.number);
result.negative=negative!=other.negative;
result=result*other;
result=*this-result;
return result;
}
int256& operator+=(const int256& other) {
*this = *this + other;
return *this;
}
int256& operator-=(const int256& other) {
*this = *this - other;
return *this;
}
int256& operator*=(const int256& other) {
*this = *this * other;
return *this;
}
int256& operator/=(const int256& other) {
*this = *this / other;
return *this;
}
int256& operator%=(const int256& other) {
*this = *this % other;
return *this;
}
/*
int256& operator=(int &other)
{
string that;
this->negative=(other>=0?0:1);
while(other)that+=(other%10)+48,other/=10;
for(int i=that.size()-1;i;--i)
{
this->number+=that[i];
}
return *this;
}
*/
static int256 sqrt(int256 &n)
{
if(n.negative)throw std::runtime_error("negative has no square root");
int256 l,r=n,ans;
l.number="0";l.negative=0;
ans.number="0";ans.negative=0;
int256 dou,one;
dou.number="2";dou.negative=0;
one.number="1";one.negative=0;
for(;l<=r;)
{
int256 mid=(l+r)/dou;
if((mid*mid)<=n)ans=mid,l=mid+one;
else r=mid-one;
}
return ans;
}
private:
std::string aresult(const std::string& a, const std::string& b) const {
std::string result;
int carry = 0;
int i = a.length() - 1;
int j = b.length() - 1;
while (i >= 0 || j >= 0 || carry != 0) {
int digit1 = (i >= 0) ? (a[i] - '0') : 0;
int digit2 = (j >= 0) ? (b[j] - '0') : 0;
int sum = digit1 + digit2 + carry;
carry = sum / 10;
sum = sum % 10;
result = std::to_string(sum) + result;
--i;
--j;
}
std::size_t pos = result.find_first_not_of('0');
if (pos != std::string::npos) {
result = result.substr(pos);
} else {
result = "0";
}
return result;
}
std::string subtract(const std::string& a, const std::string& b) const {
std::string result;
int borrow = 0;
int i = a.length() - 1;
int j = b.length() - 1;
while (i >= 0 || j >= 0) {
int digit1 = (i >= 0) ? (a[i] - '0') : 0;
int digit2 = (j >= 0) ? (b[j] - '0') : 0;
int diff = digit1 - digit2 - borrow;
if (diff < 0) {
diff += 10;
borrow = 1;
} else {
borrow = 0;
}
result = std::to_string(diff) + result;
--i;
--j;
}
std::size_t pos = result.find_first_not_of('0');
if (pos != std::string::npos) {
result = result.substr(pos);
} else {
result = "0";
}
return result;
}
/*
std::string multiply(const std::string& a, const std::string& b) const {
int len1 = a.length();
int len2 = b.length();
std::string result(len1 + len2, '0');
for (int i = len1 - 1; i >= 0; --i) {
int carry = 0;
int n1 = a[i] - '0';
for (int j = len2 - 1; j >= 0; --j) {
int n2 = b[j] - '0';
int sum = n1 * n2 + carry + (result[i + j + 1] - '0');
carry = sum / 10;
result[i + j + 1] = sum % 10 + '0';
}
result[i] += carry;
}
std::size_t pos = result.find_first_not_of('0');
if (pos != std::string::npos) {
result = result.substr(pos);
} else {
result = "0";
}
return result;
}
*/
int revv(int x, int bits)
{
int ret = 0;
for (int i = 0; i < bits; i++)
{
ret <<= 1;
ret |= x & 1;
x >>= 1;
}
return ret;
}
void fft(double * a, double * b, int n, bool rev)
{
int bits = 0;
while (1 << bits < n) ++bits;
for (int i = 0; i < n; i++)
{
int j = revv(i, bits);
if (i < j)
swap(a[i], a[j]), swap(b[i], b[j]);
}
for (int len = 2; len <= n; len <<= 1)
{
int half = len >> 1;
double wmx = cos(2 * acos(-1.0) / len), wmy = sin(2 * acos(-1.0) / len);
if (rev) wmy = -wmy;
for (int i = 0; i < n; i += len)
{
double wx = 1, wy = 0;
for (int j = 0; j < half; j++)
{
double cx = a[i + j], cy = b[i + j];
double dx = a[i + j + half], dy = b[i + j + half];
double ex = dx * wx - dy * wy, ey = dx * wy + dy * wx;
a[i + j] = cx + ex, b[i + j] = cy + ey;
a[i + j + half] = cx - ex, b[i + j + half] = cy - ey;
double wnx = wx * wmx - wy * wmy, wny = wx * wmy + wy * wmx;
wx = wnx, wy = wny;
}
}
}
if (rev)
{
for (int i = 0; i < n; i++)
a[i] /= n, b[i] /= n;
}
}
int solve(int a[],int na,int b[],int nb,int ans[])
{
int len = max(na, nb), ln;
for(ln=0; 1<<ln<len; ++ln);
len=(1<<(++ln));
for (int i = 0; i < len ; ++i)
{
if (i >= na) ax[i] = 0, ay[i] =0;
else ax[i] = a[i], ay[i] = 0;
}
fft(ax, ay, len, 0);
for (int i = 0; i < len; ++i)
{
if (i >= nb) bx[i] = 0, by[i] = 0;
else bx[i] = b[i], by[i] = 0;
}
fft(bx, by, len, 0);
for (int i = 0; i < len; ++i)
{
double cx = ax[i] * bx[i] - ay[i] * by[i];
double cy = ax[i] * by[i] + ay[i] * bx[i];
ax[i] = cx, ay[i] = cy;
}
fft(ax, ay, len, 1);
for (int i = 0; i < len; ++i)
ans[i] = (int)(ax[i] + 0.5);
return len;
}
std::string multiply( std::string sa, std::string sb)
{
int l1,l2,l;
int i;
string ans;
l1 = sa.size();
l2 = sb.size();
memset(sum,0,sizeof(sum));
for(i = 0; i < l1; i++)
x1[i] = sa[l1 - i - 1]-'0';
for(i = 0; i < l2; i++)
x2[i] = sb[l2-i-1]-'0';
l = solve(x1, l1, x2, l2, sum);
for(i = 0; i<l || sum[i] >= 10; i++) // 进位
{
sum[i + 1] += sum[i] / 10;
sum[i] %= 10;
}
l=i;
while(sum[l] <= 0 && l>0)l--; // 检索最高位
for(i = l; i >= 0; i--)ans+=sum[i] + '0'; // 倒序输出
return ans;
}
std::string divide(const std::string& aq, const std::string& bg)const
{
int x=0,y=0,z=0,w=0,i,j,p;
int a[100000],b[100000],c[100000],d[100000];
int la=aq.size();
int lb=bg.size();
for(i=1;i<=la;++i)a[i]=aq[la-i]-'0';
for(i=1;i<=lb;++i)b[i]=bg[lb-i]-'0';
for(i=lb;i<=la;++i)
{
for(j=0;j<=10;++j)
{
y=1;
for(p=1;p<=lb+10;p++)d[p]=0;
for(p=1;p<=lb+1;p++)
{
d[p]=(b[p]*j+x)%10;
x=(b[p]*j+x)/10;
}
x=0;
for(p=la-i+lb+1;p>=la-i+1;--p)
{
if(d[p-la+i]>a[p]){y=0;break;}
if(d[p-la+i]<a[p]){y=1;break;}
}
for(p=1;p<=lb+10;++p) d[p]=0;
if(y==0){z=j-1;break;}
}
c[i+1-lb]=z;
for(p=1;p<=lb+1;p++){d[p]=(b[p]*z+x)%10;x=(b[p]*z+x)/10;}
x=0;
for(j=la-i+1;j<=la+lb-i+1;++j)
{
if(a[j]<d[j-la+i])--a[j+1],a[j]+=10;
a[j]=a[j]-d[j-la+i];
}
}
std::string result;
int as=la-lb+1;
i=1;
while(c[i]==0&&i<=as)++i;
while(i<=as)result+=c[i++]+48;
std::size_t pos = result.find_first_not_of('0');
if(pos != std::string::npos){
result = result.substr(pos);
} else {
result = "0";
}
return result;
}
int abs_compare(const std::string& a, const std::string& b) const {
if (a.length() < b.length()) {
return -1;
} else if (a.length() > b.length()) {
return 1;
} else {
return a.compare(b);
}
}
};
int256 a[1000100],b[1000100],sum;
bool cmp(int x,int y)
{
return x<y;
}
using namespace std;
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
//freopen("nj.in","r",stdin);
//freopen("nj.out","w",stdout);
int i,j,m,n;
cin>>n;
for(i=1;i<=n;i++)cin>>a[i];
for(i=1;i<=n;i++)cin>>b[i];
stable_sort(a+1,a+n+1);
stable_sort(b+1,b+n+1);
for(i=1;i<=n;i++)sum+=a[i]*b[i];
cout<<sum;
}
不水int256了。
\(AC\) 代码。(虽然很简陋)
//凑合看吧
#include <bits/stdc++.h>
#define int long long
using namespace std;
int n,sum=0,flag=0;
int a[1100001],b[1100001];
signed main(void)
{
//freopen("nj.in","r",stdin);
//freopen("nj.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int i,j,k,m;
cin>>n;
for(i=1;i<=n;i++)
cin>>a[i];
for(i=1;i<=n;i++)
cin>>b[i];
sort(a+1,a+n+1);
sort(b+1,b+n+1);
for(i=1;i<=n;i++)sum+=a[i]*b[i];
cout<<sum;
}
T3 翻转
\(0pts\) 搜索题,没打。
也许可以去看看其他大佬的文章?
T4 阶乘
\(0pts\) 当时打表,结果 \(CE\) 了。
- 首先,阶乘的增长速度极快
1!: 1
2!: 2
3!: 6
4!: 24
5!: 120
6!: 720
7!: 5040
8!: 40320
9!: 362880
10!: 3628800
11!: 39916800
12!: 479001600
13!: 6227020800
14!: 87178291200
15!: 1307674368000
16!: 20922789888000
17!: 355687428096000
18!: 6402373705728000
19!: 121645100408832000
20!: 2432902008176640000
仅仅是 \(20!\) 就已经达到了 \(2432902008176640000\) ,而 \(21!\) 已经超过了 \(long long\) 的存储范围。
- 因此我们可以在一个较小的区间内枚举(而且范围是连续的,很方便枚举),区间大约在 \(\Large{\sqrt[i]{n}}\) 左右, \(\large{(i为阶乘长度,大约枚举到20左右即可)}\) 。
- 可以使用优先队列来存储每次得到的结果,(本来我用的结构体,但是莫名其妙的 \(TLE\) ,就算只有一个数据也要用几百毫秒,改成优先队列只需要 \(89ms\) ),这样得到的结果就是有序的,但是要注意优先队列默认从大到小排序,因此可以存负值或者写小根堆。
- 当然,\(\Large{\dfrac{n!}{(n-1)!}}\) 的值是等于 \(n\) 的,因此可以不枚举 \(i=1\) 的情况。并且当 \(n=1\) 时,有无数解 \((\Large{\dfrac{n!}{n!}=1})\) 所以可以特判。
- 由于 \(long long\) 最大可以存到 \(20!\) ,因此可以预处理 \(1\) 到 \(20\) 的阶乘
(以便卡常)。
\(\large{AC}\) \(\large{Code}\)
#include<bits/stdc++.h>
#define int long long
using namespace std;
int fac[30][30];
inline int read(){
int x=0,f=1;
char s=getchar();
for(;s<'0'||s>'9';s=getchar()) if(s=='-') f=-1;
for(;'0'<=s&&s<='9';s=getchar()) x=(x<<1)+(x<<3)+(s^48);
return x*f;
}
void write(int x){
if(x<0) x=-x,putchar('-');
if(x>9) write(x/10);
putchar(x%10+48);
}
priority_queue<pair<int,int> >res;
signed main(void)
{
//freopen("jc.in","r",stdin);
//freopen("jc.out","w",stdout);
int i,j,k,m,t,n;
int cnt=1;
for(i=1;i<=20;i++)
{
fac[i][i]=i;
for(j=i+1;j<=20;++j)
fac[i][j]=fac[i][j-1]*j;
}
t=read();
while(t--)
{
cnt=1;
n=read();
if(n==1){printf("-1\n");continue;}
res.push(make_pair(-n,-n+1));
for(i=2;i<=20;++i)
{
int x=pow(n*1.0,1.0/i);
while(k<n)
{
int y=x-i+1;
int k=1;
if(y-1>0)
{
if(x<=20)
{
k=fac[y][x];
if(k>n)break;
if(k==n){++cnt;res.push(make_pair(-x,-y+1));break;}
}
else
{
for(j=y;j<=x;++j)k*=j;
if(k>n)break;
if(k==n){++cnt;res.push(make_pair(-x,-y+1));break;}
}
}
x++;
}
}
write(cnt);printf("\n");
for(i=cnt;i>=1;--i)
write(-res.top().first),printf(" "),write(-res.top().second),printf("\n"),res.pop();
}
}