周赛98补题
题目意思:
给定一个数字判断加上自身任意因子数,是否能成为一个奇数。
思路:
我们想一个最简单的判断方法, 任意的数字的因子数都有1,故,最简单的方法就是判断奇偶。
奇数+1成偶数,偶数+1成奇数。
#include <bits/stdc++.h>
using namespace std;int main() {int n;cin>>n;if(!(n&1)){cout<<"Yes"<<endl;}else{cout<<"No"<<endl;}
}
题目意思:
给定一个字符串用最小操作的次数来使得字符串中的所有相邻的字母都不相同。
思路:
贪心的从第二个字母开始,对两边的字母进行判断,如果存在与周围两个字母相同的情况,换位替换即可。
#include <bits/stdc++.h>
using namespace std;
inline void solve() {int n;cin>>n;string ac;cin>>ac;string answer="red";for(int i=1;i<n;i++){if(ac[i]==ac[i-1]){for(int j=0;j<answer.size();j++){if(answer[j]!=ac[i]&&answer[j]!=ac[i+1]){ac[i]=answer[j];break;}}}}cout<<ac<<endl;
}
int main() {int n=1;//cin>>n;while(n--)solve();
}
题目意思:
给定一个数字,构造所有可能的数组,满足数组中无相邻且相同的情况,按照字典序列输出所有可能的情况。
思路:
谈论构造,我们可以不断的用1 2 1 2来进行构造数组,依照上述想法,我们很快想到dfs 的做法。
dfs(int last,int sum,int u)last是数组中前一个数字,sum是到目前为止数字之和,u是当前第几个数字。
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int op=12;
int path[op];
int n;
void dfs(int last,int sum,int u){if(sum==n){for(int i=0;i<u;i++){cout<<path[i];if(i!=u-1){cout<<" ";}//不是最后一个的情况下}cout<<endl;return;}for(int i=1;i<=n-sum;i++){if(u>0&&i==last)continue;//如果说当前选择的数字等于前面一个数字的情况下,而且选择的数字是不是第一个数字path[u]=i;//在第u个位置上赋值i;dfs(i,sum+i,u+1);//前面一个位置的数字是i,当前所有数字的和是sum+i,位置是u+1当下}
}
signed main(){cin>>n;dfs(-1,0,0);return 0;
}
题目意思:
给定一个数组,找出一个子数组满足数组内(所有数字之和)和gcd(数组内所有数字)的积最大。
思路1:
要找gcd和sum之积最大,我们直接不断的对gcd进行枚举,sum表示的是所有的数字之和,自然而然数字越多越好。
故我们只需要遍历gcd 的可能性,最后不断的讲满足条件的数字加入到sum中,求个最大值即可。
思路2:
和思路1大相径庭,也是对因子数动手,枚举数组中各个数字的所有因子,用一个map存储该数组中所有拥有同一个因子的总和。
#include<bits/stdc++.h>
using namespace std;
#define int long long
signed main(){int n,m;cin>>n;m=1e6+4;vector<int>cnt(m+1,0);int ans=0;for(int i=1,x;i<=n;i++){cin>>x;cnt[x]++;//桶排序}for(int g=1;g<=m;g++){//对gcd中的公共g进行枚举int c=0;for(int j=g;j<=m;j+=g){//如果说一个数是g的公倍数的话,那么满足因子里面一定有gc+=cnt[j]*j;//c代表的是sum的总和}//c是sum的最优解//对g进行不断地枚举ans=max(ans,c*g);//c*g是题目要求的贡献}cout<<ans<<endl;
}
#include <bits/stdc++.h>
using namespace std;
#define int long long
inline void solve() {int n;cin>>n;vector<int>a(n+1);for(int i=1;i<=n;i++)cin>>a[i];map<int,int>p;for(auto i:a){//枚举a中的所有数字for(int j=1;j<= sqrt(i);j++){//对因子进行枚举if(i%j==0){p[j]+=i;//i中有j因子数if(j*j!=i){//如果不是平方的情况下p[i/j]+=i;}}}}int sum=0;for(auto it:p){//这样一来second有的就是所有满足的sum,而first就是因子int cnt=it.first*it.second;sum=max(cnt,sum);//取最大}cout<<sum<<endl;
}
signed main() {int nc=1;//cin>>n;while(nc--)solve();
}
题目意思:
给定一个数组a,数组b第i个数是对应数组a中第i个数的因子个数。
求给出n,数组b前n个数之和。
思路:
纯粹的数学题目,我们先对a数组进行分析。
22的2次方,22的22次方,22的2222次方....
上述数字可以拆解成,(2*11)的2次方,(2*11)的22次方,(2*111)的222次方。
而2和11都是质数,故(2*11)的2次方内因子的个数可以表示成(2+1)*(2+1)
因为(2*11)的2次方=(2)的2次方*(11)的2次方,对于每一个2和11存在(次方数字+1)的取法,+1是因为存在不取的情况。
如此一来便有
(2*11)的22次方的因子个数是(22+1)的平方
(2*11)的222次方的因子个数是(222+1)的平方
b数组内各个数如下:
(2+1)的平方,(22+1)的平方,(222+1)的平方....
题目要求求出b数组前n个数之和。
故我们对每一个数字展开:
2*2+2*2*1+1
22*22+2*22*1+1
222*222+2*222*1+1
.....
第一项我们进行改写成:
4*(1*1)
4*(11*11)
4*(111*111)
第二项我们改写成:
4*1
4*11
4*111
即:4*ci(c1=1,c2=11,c3=111....)
我们对ci进行数学归纳写出表达式为(10的i次-1)/9
而第一项就成为了4*(10的i次-1)/9 *(10的i次-1)/9
对ci进行前n项求和,等比数列求前n项和(10的i+1次-1-9*i)/81--------这个自己去推一边好了
然后再对ci的平方求一遍前n项和,这次是等差乘上等比求和
即(100的i次/81+n/81-2*10的i次/81)求前n项之和
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int mod = 998244353;
int ksm(int a, int b) {int res = 1;a %= mod;while (b) {if (b & 1) res = res * a % mod;a = a * a % mod;b >>= 1;}return res;
}
void solve() {int x;cin >> x;int inv9 = ksm(9, mod - 2);int inv81 = inv9 * inv9 % mod;int inv99 = ksm(99, mod - 2);// 计算 a:与 100 的幂次相关int a = ((ksm(100, x + 1)) - 100 + mod) % mod; // 计算 (100^(x+1) - 100) mod moda = a * inv99 % mod; // 乘以 99 的逆元// 计算 b:与 10 的幂次相关int b = (ksm(10, x + 1) - 10 + mod) % mod; // 计算 (10^(x+1) - 10) mod modb = b * inv9 % mod; // 乘以 9 的逆元x %= mod;//x可能取比较大,需要对x进行向下取模//也可以用欧拉降幂//x=n%(mod-1)+(mod-1)int xx = 4 * a % mod+(28*b)%mod+(49*x)%mod; // 4*a+28*b+49*xcout << (xx * inv81) % mod << endl; // 乘以 81 的逆元后输出
}
signed main() {int T = 1;while (T--) {solve();}return 0;
}