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

\(1\)\(1000\) 的阶乘

也可以打开这个?

仅仅是 \(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();
    }
}

\(\Huge{写完了?}...\)

\(\Huge但是打了一场模拟赛,又垫底了。qwq\)

posted @ 2023-08-20 07:45  minecraft114514  阅读(53)  评论(0编辑  收藏  举报