22/6/24~6/25

1,cf Palindromic Numbers;2,牛牛看云;3,中位数切分;4,cf Another Problem About Dividing Numbers;5,九小时九个人九扇门;


1,cf Palindromic Numbers

题意:给你一个长度为n的正整数,一定存在另一个长度也为n的数,使得他俩的和为回文数;求出另一个数;

思路:看正整数开头的数字,在1~8就可以用长度为n的999....来当回文数,再减去给出的数字,就可得到长度为n的另一个数,如果开头数字是9,那么我选择的是长度为n+1的111....,用到了高精度减法;

高精度减法复习:

(A的长度>B的长度 ,每次存的是(t+10)%10,这样做的好处就是不用特判t<0是否需要借数等,直接在后面特判,t<0,说明需要借1,t=1,这样下一轮t=A[i]-t,就会少1,最后除去前导0的操作); 

code:

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define rep1(i,a,n) for( int i=a;i<n;++i) 
#define rep2(i,a,n) for( int i=a;i<=n;++i) 
#define per1(i,n,a) for( int i=n;i>a;i--) 
#define per2(i,n,a) for( int i=n;i>=a;i--)
#define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false)
#define memset(a,i,b) memset((a),(i),sizeof (b))
#define memcpy(a,i,b) memcpy((a),(i),sizeof (b))
#define pro_q priority_queue
#define pb push_back
#define pf push_front
#define endl "\n"
#define lowbit(m) ((-m)&(m))
#define YES cout<<"YES\n"
#define NO cout<<"NO\n"
#define Yes cout<<"Yes\n"
#define No cout<<"No\n"
#define yes cout<<"yes\n"
#define no cout<<"no\n"
#define yi first
#define er second
using namespace std;
typedef pair<long long,long long>PLL;
typedef long long LL;
typedef pair<int,int> PII;
typedef pair<int,PII> PIII;
typedef double dob; 
const int N=1e5+10;
char a[N];
vector<int> sub(vector<int>A,vector<int>B)
{
    vector<int>C;
    int t=0;
    int asiz=A.size();
    int bsiz=B.size();
    rep1(i,0,asiz)
    {
        t=A[i]-t;
        if(i<bsiz)t-=B[i];
        C.pb((t+10)%10);
        if(t<0)t=1;
        else t=0;
    }
    while(C.size()>1&&C.back()==0)C.pop_back();
    return C;
}
void solve()
{
    int n;
    cin>>n;
    rep2(i,1,n)cin>>a[i];
    if(a[1]=='9')
    {
        vector<int>A,B;
        rep2(i,1,n+1)A.push_back(1);
        per2(i,n,1)B.push_back(a[i]-'0');
        auto C=sub(A,B);
        int csiz=C.size();
        per2(i,csiz-1,0)cout<<C[i];
        cout<<endl;
    }
    else
    {
        vector<int>A,B;
        rep2(i,1,n)A.pb(9);
        per2(i,n,1)B.pb(a[i]-'0');
        auto C=sub(A,B);
        int csiz=C.size();
        per2(i,csiz-1,0)cout<<C[i];
        cout<<endl;
    }
}
signed main()
{
    quick_cin();
    int T;
    cin>>T;
    while(T--)solve();
    return 0;
}

 2,牛牛看云;

 思路:直接按公式做肯定是tle的,看序列的数据范围,只有1000,所以可以记录0~1000的每个数的出现次数,然后转换下求法即可;

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define rep1(i,a,n) for( int i=a;i<n;++i) 
#define rep2(i,a,n) for( int i=a;i<=n;++i) 
#define per1(i,n,a) for( int i=n;i>a;i--) 
#define per2(i,n,a) for( int i=n;i>=a;i--)
#define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false)
#define memset(a,i,b) memset((a),(i),sizeof (b))
#define memcpy(a,i,b) memcpy((a),(i),sizeof (b))
#define pro_q priority_queue
#define pb push_back
#define pf push_front
#define endl "\n"
#define lowbit(m) ((-m)&(m))
#define YES cout<<"YES\n"
#define NO cout<<"NO\n"
#define Yes cout<<"Yes\n"
#define No cout<<"No\n"
#define yes cout<<"yes\n"
#define no cout<<"no\n"
#define yi first
#define er second
using namespace std;
typedef pair<long long,long long>PLL;
typedef long long LL;
typedef pair<int,int> PII;
typedef pair<int,PII> PIII;
typedef double dob; 
const int N=1e6+10;
LL cs[N];
LL ans;
signed main()
{
    quick_cin();
    int n;
    cin>>n;
    rep2(i,1,n)
    {
        int x;
        cin>>x;
        cs[x]++;
    }
    rep2(i,0,1000)
    {
        LL num=0;
        rep2(j,i,1000)
        {
            if(j==i)num=((cs[i]+1)*cs[i])/2;
            else num=cs[i]*cs[j];
            ans+=num*abs(i+j-1000);
        }
    }
    cout<<ans;
    return 0;
}

3,中位数切分;

数学题:

结论:设cnt1为>=m的数的个数,cnt2为<m的个数,如果cnt1>cnt2,则ans=cnt1-cnt2;否则就是-1;

证明:

设f(l,r)为数组al到ar的cnt1-cnt2的值,很明显f(l,r)>1才是符合要求的区间;

f(l,r)的性质:f(l,r)=f(l,mid)+f(mid+1,r);

要找的就是存在一个位置mid,使得f(l,mid)>0&&f(mid+1,r)>0;

看f(l,mid)=1的情况,此时f(l,r)>1,所以f (mid+1,r)=f(l,r)-f(l,mid)>0,所以此时就可以切;

为了切最多的区间,肯定是f(l,r)=1;

又因为整个在f(1,n)区间进行切割,所以总的和等于f(1,n)=cnt1-cnt2;

code:

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define rep1(i,a,n) for( int i=a;i<n;++i) 
#define rep2(i,a,n) for( int i=a;i<=n;++i) 
#define per1(i,n,a) for( int i=n;i>a;i--) 
#define per2(i,n,a) for( int i=n;i>=a;i--)
#define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false)
#define memset(a,i,b) memset((a),(i),sizeof (b))
#define memcpy(a,i,b) memcpy((a),(i),sizeof (b))
#define pro_q priority_queue
#define pb push_back
#define pf push_front
#define endl "\n"
#define lowbit(m) ((-m)&(m))
#define YES cout<<"YES\n"
#define NO cout<<"NO\n"
#define Yes cout<<"Yes\n"
#define No cout<<"No\n"
#define yes cout<<"yes\n"
#define no cout<<"no\n"
#define yi first
#define er second
using namespace std;
typedef pair<long long,long long>PLL;
typedef long long LL;
typedef pair<int,int> PII;
typedef pair<int,PII> PIII;
typedef double dob; 
const int N=1e6+10;
int n,m;
void solve()
{
    cin>>n>>m;
    int cnt1=0,cnt2=0;
    rep2(i,1,n)
    {
        int x;
        cin>>x;
        if(x>=m)cnt1++;
        else cnt2++;
    }
    if(cnt1>cnt2)cout<<cnt1-cnt2<<endl;
    else cout<<-1<<endl;
}
signed main()
{
    quick_cin();
    int T;
    cin>>T;
    while (T--)
    {
        solve();
    }
    return 0;
}

4, cf Another Problem About Dividing Numbers

题意:

思路:求出来最小操作次数和最多操作次数即可;对于a=b&&k=1的情况进行特判;

最小操作次数:

a=b,0;

a!=b,a!=gcd(a,b)&&b!=gcd(a,b)时为2,否则为1;

最大操作次数:

a与b的质因数个数之和;

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define rep1(i,a,n) for( int i=a;i<n;++i) 
#define rep2(i,a,n) for( int i=a;i<=n;++i) 
#define per1(i,n,a) for( int i=n;i>a;i--) 
#define per2(i,n,a) for( int i=n;i>=a;i--)
#define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false)
#define memset(a,i,b) memset((a),(i),sizeof (b))
#define memcpy(a,i,b) memcpy((a),(i),sizeof (b))
#define pro_q priority_queue
#define pb push_back
#define pf push_front
#define endl "\n"
#define lowbit(m) ((-m)&(m))
#define YES cout<<"YES\n"
#define NO cout<<"NO\n"
#define Yes cout<<"Yes\n"
#define No cout<<"No\n"
#define yes cout<<"yes\n"
#define no cout<<"no\n"
#define yi first
#define er second
using namespace std;
typedef pair<long long,long long>PLL;
typedef long long LL;
typedef pair<int,int> PII;
typedef pair<int,PII> PIII;
typedef double dob; 
const int N=1e6+10;
int a,b,k;
inline int gcd(int a,int b)
{
    if(b)while((a%=b)&&(b%=a));
    return a+b;
}
int zhi(int num)
{
    int ans=0;
    for(int i=2;i*i<=num;i++)
    {
        while(num%i==0)
        {
            num/=i;
            ans++;
        }
    }
    if(num!=1)ans++;
    return ans;
}
int xiao(int a,int b)
{
    int ans=0;
    int num=gcd(a,b);
    if(a!=num)ans++;
    if(b!=num)ans++;
    return ans;
}
int da(int a,int b)
{
    return zhi(a)+zhi(b);
}
void solve()
{
    cin>>a>>b>>k;
    if(xiao(a,b)<=k&&k<=da(a,b)&&(a!=b||k!=1))YES;
    else NO;
}
signed main()
{
    quick_cin();
    int T;
    cin>>T;
    while (T--)
    {
        solve();
    }
    return 0;
}

 5,九小时九个人九扇门

题意:

 数字根的结论:一个数的数字根是它%9的结果;

一个四位数abcd%9=(a*1000+b*100+c*10+d)%9=(a+b+c+d)%9;

问题转化为: 从a数组中选择一些数字,使得其求和对9取模为0,1,2,3,4,5,6,7,8有多少种选法

最后记得-1,不能一个也不选;

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define rep1(i,a,n) for( int i=a;i<n;++i) 
#define rep2(i,a,n) for( int i=a;i<=n;++i) 
#define per1(i,n,a) for( int i=n;i>a;i--) 
#define per2(i,n,a) for( int i=n;i>=a;i--)
#define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false)
#define memset(a,i,b) memset((a),(i),sizeof (b))
#define memcpy(a,i,b) memcpy((a),(i),sizeof (b))
#define pro_q priority_queue
#define pb push_back
#define pf push_front
#define endl "\n"
#define lowbit(m) ((-m)&(m))
#define YES cout<<"YES\n"
#define NO cout<<"NO\n"
#define Yes cout<<"Yes\n"
#define No cout<<"No\n"
#define yes cout<<"yes\n"
#define no cout<<"no\n"
#define yi first
#define er second
using namespace std;
typedef pair<long long,long long>PLL;
typedef long long LL;
typedef pair<int,int> PII;
typedef pair<int,PII> PIII;
typedef double dob; 
const int N=1e6+10;
LL f[N][9];
const int mod=998244353;
signed main()
{
    quick_cin();
    int n;
    cin>>n;
    f[0][0]=1;
    rep2(i,1,n)
    {
        int x;
        cin>>x;
        rep1(j,0,9)
        {
            f[i][(j+x)%9]=(f[i][(j+x)%9]+f[i-1][j])%mod;
            f[i][j]=(f[i][j]+f[i-1][j])%mod;
        }
    }
    rep2(i,1,8)cout<<f[n][i]<<" ";
    cout<<f[n][0]-1;
    return 0;
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Dull丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值