1 条题解

  • 0
    @ 2025-5-5 15:08:03

    解题思路

    本题旨在求解由红、蓝、绿三色珠子组成的(n)颗珠子圆形项链,在忽略旋转和翻转重复情况下的不同形式数量。

    1. 计算初始状态数量power函数用于计算(3)的(e)次幂。在不考虑旋转和翻转重复时,每颗珠子有(3)种颜色选择,(n)颗珠子的项链组合数为(3^n) ,在transf函数中通过power(n)得到此值并赋给add
    2. 考虑旋转对称情况: 通过枚举旋转间隔(d)((1)到(n - 1) )来处理旋转对称。对于每个(d),利用while循环标记访问过的珠子(借助visit数组 ),计算在该旋转间隔下的循环节数量res 。每个循环节内珠子颜色组合数为(3^res) ,将其累加到add中。这是因为旋转对称会使一些组合重复,需将这些重复组合按不同旋转情况统计并累加。
    3. 考虑翻转对称情况: 根据(n)的奇偶性分别处理翻转对称。
      • 当(n)为奇数时,对称轴过一颗珠子和圆心,有(n)条对称轴。对于每条对称轴,对称轴两侧珠子对称,此时对称轴一侧珠子组合数为(3^{\frac{n + 1}{2}}) ,所以这部分组合数为(n\times3^{\frac{n + 1}{2}}) ,累加到add中,同时mapnum加上(n) 。
      • 当(n)为偶数时,有两种对称轴:一种过相对两颗珠子的中点和圆心,共(\frac{n}{2})条,每条对称轴对应一侧珠子组合数为(3^{\frac{n}{2}+1}) ;另一种过相对两颗珠子和圆心,共(\frac{n}{2})条,每条对称轴对应一侧珠子组合数为(3^{\frac{n + 1}{2}}) 。将这两部分组合数分别累加,同时mapnum加上(n) 。
    4. 计算最终结果: 将考虑旋转和翻转对称后的总组合数add除以总的对称情况数mapnum ,得到不同形式项链的数量并返回。在main函数中循环读取输入的(n),调用transf函数输出结果。
    #include<iostream>
    using namespace std;
    
    #include <cstring> 
    int n;
    bool visit[100];
    
    long long power(int e){
        long long res = 3;
        for(int i = 1; i < e; i++)
                res *= 3;
        return res;
    }
    
    long long transf(){
         if(n==0) return 0;
        long long add = power(n),mapnum = n;
        for(int d = 1; d < n; d++){
            memset(visit,0,sizeof(visit));
            int res = 0, cnt = 0;
            while(cnt<n){
                         int st = 0;
                         while(visit[st]) st++;
                         
                         while(visit[st]==0)
                                            visit[st] = 1, cnt++, st = (st+d)%n;
                         res++;
            }
            
            add += power(res);
        }
        //cout << add << endl;
        if(n%2){
                int t = power((n+1)/2);
                add += n*t;
                mapnum += n;
        }
        else{
             int t = power((n+1)/2);
             add += n/2*t+n/2*power(n/2+1);
             mapnum += n;
        }
        
        //cout << add << " " << mapnum << endl;
        //add += power((n+1)/2);
        return add/mapnum;
    }
        
    
    int main(){
        while(cin>>n&&n!=-1){
                      cout << transf() << endl;
        }
    }
    • 1

    信息

    ID
    287
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    6
    已通过
    1
    上传者