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;
- }