• AC修炼计划(AtCoder Regular Contest 167)


    传送门:AtCoder Regular Contest 167 - AtCoder

    再次感谢樱雪喵大佬的题解,讲的很详细,Orz。

    大佬的博客链接如下:Atcoder Regular Contest 167 - 樱雪喵 - 博客园 (cnblogs.com)

    第一题很签到,就省略掉了。

    第二题其实也不算难,要想清楚因子之间的关系(可是本人没长脑子被卡了俩小时)。通过分解质因数来得出最后的数有多少个因子,然后两两匹配,如果因子个数是奇数,说明存在完全平方数因子的情况,于是单独计算出这样的贡献。

    代码如下:

    1. #include
    2. using namespace std;
    3. #define int long long
    4. typedef long long ll;
    5. typedef pair<int,int> PII;
    6. const int N=998244353;
    7. const int MX=0x3f3f3f3f3f3f3f3f;
    8. // void read(__int128 &x)
    9. // {
    10. // x=0;
    11. // int f=1;
    12. // char ch;
    13. // if((ch=getchar())=='-')
    14. // f=-f;
    15. // else
    16. // x=x*10+ch-'0';
    17. // while((ch=getchar())>='0'&&ch<='9')
    18. // x=x*10+ch-'0';
    19. // x*=f;
    20. // }
    21. // void print(__int128 x){
    22. // if(x<0){
    23. // putchar('-');
    24. // x=-x;
    25. // }
    26. // if(x>9)
    27. // print(x/10);
    28. // putchar(x%10+'0');
    29. // }
    30. int n,m;
    31. int an;
    32. int su[1000005];
    33. bool c[1000005];
    34. void suu(int x){
    35. for(int i=2;i<=x;i++){
    36. if(!c[i])su[++an]=i;
    37. for(int j=1;j<=an&&su[j]*i<=x;j++){
    38. c[su[j]*i]=1;
    39. if(i%su[j]==0)break;
    40. }
    41. }
    42. }
    43. int kuai(int a,int b){
    44. int ans=1;
    45. while(b){
    46. if(b&1)ans=ans*a%N;
    47. b>>=1;
    48. a=a*a%N;
    49. }
    50. return ans%N;
    51. }
    52. void icealsoheat(){
    53. cin>>n>>m;
    54. int bn=n;
    55. if(m==0){
    56. cout<<0;
    57. return;
    58. }
    59. vectorve;
    60. for(int i=1;i<=an&&su[i]<=sqrt(n);i++){
    61. if(n%su[i]==0){
    62. ve.push_back({su[i],0});
    63. while(n>1&&n%su[i]==0){
    64. ve.back().second++;
    65. n/=su[i];
    66. }
    67. }
    68. }
    69. if(n>1){
    70. ve.push_back({n,1});
    71. }
    72. int sum=1;
    73. int cnt=0;
    74. for(auto [i,j]:ve){
    75. if(m%2==1&&j%2==1)cnt=1;
    76. sum=sum*(m%N*j%N+1ll)%N;
    77. }
    78. int ans=0;
    79. // ans=sum*kuai(2ll,N-2)%N*(m%N)%N;
    80. // // if(cnt==0)ans=(ans+m/2)%N;
    81. // if(cnt==0){
    82. // ans=((ans-1)%N+N)%N;
    83. // ans=ans=(ans+m/2)%N;
    84. // }
    85. if(cnt==0){
    86. sum=((sum-1)%N+N)%N;
    87. }
    88. ans=sum*kuai(2ll,N-2)%N*(m%N)%N;
    89. if(cnt==0)ans=(ans+m/2)%N;
    90. cout<
    91. }
    92. signed main(){
    93. ios::sync_with_stdio(false);
    94. cin.tie();
    95. cout.tie();
    96. suu(1000000);
    97. int _;
    98. _=1;
    99. // cin>>_;
    100. while(_--){
    101. icealsoheat();
    102. }
    103. }

    C - MST on Line++

    c,写着题的时候真的很想骂娘。没想到要在限制下标并且在各种顺序的情况下,还得考虑最小生成树的贡献。。。。。。。脑子快炸了,看大佬的代码,好不容易才磕出来。同时也学到了一种新思路。首先,计算这种排列组合题,一般都会想到求出每一个值对答案的贡献,然后相加。在用kruskal算法求最小生成树的时候,我们发现我们只用考虑边全值的大小,对其优先排列。那我们只要求出每一个Ai对应的有几个边的长度就好了。因为我们需要求的是最小值,所以,尽可能的让所有数小才是最优的,按照数值顺序来说,相邻的会尽可能的小。这里看Atcoder Regular Contest 167 - 樱雪喵 - 博客园 (cnblogs.com)

    佬的博客吧,解释的特别清楚。

    代码如下:

    1. #include
    2. using namespace std;
    3. #define int long long
    4. typedef long long ll;
    5. typedef pair<int,int> PII;
    6. const int N=998244353;
    7. const int MX=0x3f3f3f3f3f3f3f3f;
    8. int n,k;
    9. int an;
    10. int a[500005];
    11. int c[5005][5005];
    12. int f[500005];
    13. int be[500005];
    14. void init(int mx)
    15. {
    16. for(int i=0;i<=mx;i++)
    17. for(int j=0;j<=i;j++) c[i][j]=j?(c[i-1][j-1]+c[i-1][j])%N:1;
    18. }
    19. void icealsoheat(){
    20. cin>>n>>k;
    21. for(int i=1;i<=n;i++){
    22. cin>>a[i];
    23. }
    24. sort(a+1,a+1+n);
    25. be[0]=1;
    26. for(int i=1;i<=n;i++){
    27. be[i]=be[i-1]*i%N;
    28. }
    29. for(int i=1;i<=n;i++){
    30. for(int j=1;j<=k;j++){
    31. f[i]=(f[i]+(i-1)*c[n-j][i-1]%N)%N;
    32. }
    33. f[i]=be[i]*be[n-i]%N*f[i]%N;
    34. }
    35. int ans=0;
    36. for(int i=1;i<=n;i++){
    37. ans=(ans+((f[i]-f[i-1])%N+N)%N*a[i]%N)%N;
    38. }
    39. cout<
    40. }
    41. signed main(){
    42. ios::sync_with_stdio(false);
    43. cin.tie();
    44. cout.tie();
    45. int _;
    46. _=1;
    47. init(5000);
    48. // cin>>_;
    49. while(_--){
    50. icealsoheat();
    51. }
    52. }

    D - Good Permutation

    这道题最开始我是用优先队列来维护的,因为我们要找在改变次数最小的基础上,要求词序也要最小。我们不妨把所有的序列都涂上各自的颜色,看看有几种颜色,然后每个都取最小的那个,进行不断的替换。但出现了问题。因为存在会误删一些边和点的情况。

    后来看了佬的思路,感觉很奇妙,通过并查集来找所有所有的环,然后用set去维护这个环的最小值,如果当前的最小值小于后面环的最小值的话,就替换并且将两个环合并。否则我们不希望字典序变大,尽量不换。但如果这是它所在连通块的最后一个位置,必须要换,那就找后面最小的环值来替换这个值。

    代码如下:

    1. #include
    2. using namespace std;
    3. #define int long long
    4. typedef long long ll;
    5. typedef pair<int,int> PII;
    6. const int N=998244353;
    7. const int MX=0x3f3f3f3f3f3f3f3f;
    8. int n,k;
    9. int an;
    10. #include
    11. #include
    12. #include
    13. #include
    14. using namespace std;
    15. int col,tot,top,num;
    16. // int co[200010];
    17. // int dfn[200010];
    18. // int low[200010];
    19. // int a[200010];
    20. int b[200005];
    21. int pre[200005];
    22. int fa[200005];
    23. int c[200005];
    24. int siz[200005];
    25. int mn[200005];
    26. setq;
    27. int find(int x){
    28. if(fa[x]==x)return x;
    29. return fa[x]=find(fa[x]);
    30. }
    31. void icealsoheat(){
    32. cin>>n;
    33. q.clear();
    34. for(int i=1;i<=n;i++){
    35. cin>>b[i];
    36. pre[b[i]]=i;
    37. fa[i]=i;
    38. siz[i]=1;
    39. mn[i]=i;
    40. q.insert({i,i});
    41. }
    42. auto add=[&](int x,int y)->void{
    43. x=find(x);
    44. y=find(y);
    45. if(x==y)return;
    46. q.erase({mn[x],x});
    47. q.erase({mn[y],y});
    48. fa[x]=y;
    49. siz[y]+=siz[x];
    50. mn[y]=min(mn[x],mn[y]);
    51. q.insert({mn[y],y});
    52. };
    53. for(int i=1;i<=n;i++){
    54. add(i,b[i]);
    55. }
    56. // for(int i=1;i<=n;i++){
    57. // cout<
    58. // cout<
    59. // cout<
    60. // }
    61. for(int i=1;i<=n;i++){
    62. if(q.size()==1)break;
    63. auto it=q.begin();
    64. if(find(it->second)==find(i))it++;
    65. if(it->firstfind(i)]==1){
    66. int j=pre[it->first];
    67. // cout<
    68. swap(b[j],b[i]);
    69. swap(pre[b[j]],pre[b[i]]);
    70. add(i,j);
    71. }
    72. siz[find(i)]--;
    73. }
    74. for(int i=1;i<=n;i++)cout<" ";
    75. cout<<"\n";
    76. }
    77. signed main(){
    78. ios::sync_with_stdio(false);
    79. cin.tie();
    80. cout.tie();
    81. int _;
    82. _=1;
    83. cin>>_;
    84. while(_--){
    85. icealsoheat();
    86. }
    87. }

  • 相关阅读:
    带声学释放器的近海海底潜标的回收记录
    一文了解 DataLeap 中的 Notebook
    Kafka-Java一:Spring实现kafka消息的简单发送
    安装配置Kafka
    windows查看并关闭端口对应进程占用的命令
    iOS开发Swift-8-类的继承,方法重写,构造器,枚举类型,可选类型,强制解包,可选绑定,隐式可选类型...
    释放Sqlite数据库占用的多余空间
    软件流程和管理(二):Process & Formal
    云计算与大数据第8章 大数据采集习题及答案
    Mybatis条件语句 status != ““,status = 0时不生效
  • 原文地址:https://blog.csdn.net/kyrietheshy/article/details/133939760