CodeTON Round 1 (Div. 1 + Div. 2, Rated, Prizes)

本文精选了五道算法竞赛题目并提供了详细的题解思路及代码实现。包括寻找最优数对、通过操作达到特定目标值、使数组元素相等、拆分数满足特定条件以及树结构上的等和划分等问题。

A - Good Pairs

题意

找一个数对满足题目所给的公式

输出下标

题解

输出最大值和最小值的下标就行了,因为本质上就是这个点到两端的距离之和

Code

int T;
int n;
PII a[N];

void solve(){
    cin >> n;
    for (int i = 1; i <= n; i++){
        cin >> a[i].x;
        a[i].y = i;
    }

    sort(a + 1, a + 1 + n);

    cout << a[1].y << ' ' << a[n].y << endl;
}

B - Subtract Operation

题意

每次选择一个数对全体数组的数来相减,问最后剩一个数能不能时k

题解

本质上,每次操作过后两个数的相对大小关系是不会改变的。

所以说,最后剩的两个数是多少,与他们最初的差是一样的

所以对于每一个数检查一下有没有与之对应的数使得两者相加为k

Code

int T;
ll n, k;
int a[N];

void solve(){
    cin >> n >> k;
    // ll summ = 0;
    map<ll, int> m;
    int maxx = 0;
    for (int i = 1; i <= n; i++){
        cin >> a[i];
        maxx = max(a[i], maxx);
        m[a[i]]++;
    }

    for (ll i = 1; i <= n; i++){
        if(m[a[i] + k]){
            cout << "YES" << endl;
            re;
        }
    }
        cout << "NO" << endl;
}

C - Make Equal With Mod

题意

给定数组,可以选取一个数 2 ≤ k 2\leq k 2k使得,将数组中的所有元素变为 a i % k a_i \%k ai%k

若干操作后,使得数组各元素相等

题解

因为操作可以无限次,那么我们最开始的想法不妨设最后都变成0

那不就都除以这个数本身就完了吗

但是题目要求 2 ≤ k 2\leq k 2k,如果数组中出现了1的话,那么肯定是不能除以自己的,而要满足题意,那必须得是让所有的数变成1,也就是 mod 上他自己减一,就可以让他们全部都变成1了

但是如果数组中出现了两个数相差为1的情况,这时候按照上面的方法就会出现0了,之后就不会再相等了

而当数组出现了0,那么还是遵循上面第一条的情况就可以了

如果数组中出现了0和1,就符合第二种说的情况

Code

int T;
int n;
int a[N];

void solve(){
    int one = 0;
    int ok = 1;

    cin >> n;
    for (int i = 1; i <= n; i++){
        cin >> a[i];
        if(a[i] == 1)
            one = 1;
        if(i > 1 && a[i - 1] != a[i])
            ok = 0;
    }

    if(ok){
        cout << "YES" << endl;
        re;
    }

    if(one){
        sort(a + 1, a + 1 + n);
        for (int i = 2; i <= n; i++){
            if(a[i] - a[i - 1] == 1){
                cout << "NO" << endl;
                re;
            }
        }
        cout << "YES" << endl;
        re;
    }
    else cout << "YES" << Endl;
}

D - K-good

题意

给你一个数n,问能不能拆成k个数的和使这k个数模k的结果都相同

输出这个k

题解

假设我们现在n已经被拆成了k个数,即
a 1 + a 2 + a 3 + ⋯ + a k = n a_1+a_2+a_3+\cdots+a_k=n a1+a2+a3++ak=n
而这些数%k都不相同,而且有k个,那么显然这些数一定都是 0 ∼ k − 1 0 \sim k-1 0k1之间的,那么
n = k ∗ ( k − 1 ) 2 + t k n = k 2 − k + 2 t k 2 n = k 2 ∗ ( k − 1 + 2 t ) n = k ∗ ( k − 1 + 2 t ) 2 n=\frac{k*(k-1)}{2}+tk \\ n=\frac{k^2-k+2tk}{2} \\ n=\frac{k}{2}*(k-1+2t) \\ n=k*\frac{(k-1+2t)}{2} n=2k(k1)+tkn=2k2k+2tkn=2k(k1+2t)n=k2(k1+2t)
若k为奇数,则 k − 1 + 2 t k-1+2t k1+2t为偶数;若k为偶数,则 k − 1 + 2 t k-1+2t k1+2t为奇数

即无论怎样,2n必定为一寄一偶相乘得到的

那么我们可以把这个偶数求出来,当2n不能再被2整除的时候,奇数也就出来了

需要注意的是n构造的式子中,已经减了一个2的质因子

最后输出的最小值是因为等式成立的话,k+2t-1一定是大于k的,所以输出最小

Code

ll n;

void solve(){
    cin >> n;
    ll tmp = n;
    int cnt = 1;
    while(tmp % 2 == 0)
        tmp /= 2, cnt++;
    if(tmp == 1) // 不满足一寄一偶
        cout << -1 << endl;
    else{
        cout << min(tmp, 1ll << (cnt)) << endl;
    }
    cout << endl;
}

E - Equal Tree Sums

参考https://www.zhihu.com/people/pzr-84

void dfs(int u, int fa){
    if(fa != -1)
        col[u] = !col[fa];
    else
        col[u] = 1;

    for(auto v: g[u]){
        if(v != fa && !col[v]){
            dfs(v, u);
        }
    }
}

void solve(){
    cin >> n;
    for (int i = 1; i <= n; i++){
        d[i] = col[i] = 0;
        g[i].clear();
    }

    for (int i = 1; i < n; i++){
        int a, b;
        cin >> a >> b;
        d[a]++;
        d[b]++;
        g[a].pb(b);
        g[b].pb(a);
    }

    dfs(1, -1);

    for (int i = 1; i <= n; i++){
        if(col[i])
            cout << -d[i] << ' ';
        else
            cout << d[i] << ' ';
    }
    cout << endl;
}
import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Random; public class LuckyDrawWheel extends JFrame { private String[] prizes = {"一等奖", "二等奖", "三等奖", "谢谢参与", "再来一次", "优惠券"}; private int[] angles = new int[prizes.length]; private int currentAngle = 0; private boolean isSpinning = false; private JButton startButton; private JPanel wheelPanel; public LuckyDrawWheel() { setTitle("幸运大转盘"); setSize(500, 500); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLayout(new BorderLayout()); // 计算每个奖项的角度(均分360度) int anglePerPrize = 360 / prizes.length; for (int i = 0; i < prizes.length; i++) { angles[i] = anglePerPrize; } wheelPanel = new JPanel() { @Override protected void paintComponent(Graphics g) { super.paintComponent(g); drawWheel(g); } }; startButton = new JButton("开始抽奖"); startButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (!isSpinning) { startSpin(); } } }); add(wheelPanel, BorderLayout.CENTER); add(startButton, BorderLayout.SOUTH); } private void drawWheel(Graphics g) { int centerX = getWidth() / 2; int centerY = getHeight() / 2; int radius = Math.min(centerX, centerY) - 20; // 1. 绘制色块(先画色块,再画文字,避免文字被覆盖) int startAngle = currentAngle; for (int i = 0; i < prizes.length; i++) { g.setColor(getColor(i)); g.fillArc( centerX - radius, centerY - radius, radius * 2, radius * 2, startAngle, angles[i] ); startAngle += angles[i]; } // 2. 绘制文字(核心修正:调整旋转角度) startAngle = currentAngle; for (int i = 0; i < prizes.length; i++) { drawText(g, prizes[i], centerX, centerY, radius, startAngle + angles[i] / 2); startAngle += angles[i]; } // 3. 绘制指针 g.setColor(Color.BLACK); Polygon pointer = new Polygon(); pointer.addPoint(centerX, centerY - radius - 10); pointer.addPoint(centerX - 10, centerY - radius + 10); pointer.addPoint(centerX + 10, centerY - radius + 10); g.fillPolygon(pointer); } // 修正文字旋转逻辑的核心方法 private void drawText(Graphics g, String text, int centerX, int centerY, int radius, int angle) { Graphics2D g2d = (Graphics2D) g; g2d.setColor(Color.BLACK); g2d.setFont(new Font("微软雅黑", Font.BOLD, 16)); // 计算文字在扇形中的坐标 double radian = Math.toRadians(angle); int textX = centerX + (int) (radius * 0.5 * Math.sin(radian)); int textY = centerY - (int) (radius * 0.5 * Math.cos(radian)); // 关键修正:让文字“垂直”贴合扇形,旋转角度 = 扇形中间角度 - 90度 double rotateAngle = radian - Math.toRadians(90); FontMetrics fm = g2d.getFontMetrics(); int textWidth = fm.stringWidth(text); // 先旋转画布,再绘制文字,最后旋转回来 g2d.rotate(rotateAngle, textX, textY); g2d.drawString(text, textX - textWidth / 2, textY); g2d.rotate(-rotateAngle, textX, textY); } // 随机颜色(可自定义更贴合实物的颜色) private Color getColor(int index) { Color[] colors = { Color.RED, Color.BLUE, Color.GREEN, Color.YELLOW, Color.ORANGE, Color.CYAN }; return colors[index % colors.length]; } // 转盘转动逻辑(线程控制) private void startSpin() { isSpinning = true; startButton.setEnabled(false); Random random = new Random(); final int spinRounds = 5 + random.nextInt(5); // 5-9圈 final int targetAngle = random.nextInt(360); // 最终停留角度 new Thread(() -> { try { int totalRotation = 360 * spinRounds + targetAngle; int step = 10; // 初始步长 for (int i = 0; i < totalRotation; i += step) { currentAngle = (currentAngle + step) % 360; Thread.sleep(20); wheelPanel.repaint(); // 逐渐减速(模拟物理效果) if (i > totalRotation * 0.7) { step = (int) (step * 0.95); if (step < 1) step = 1; } } // 计算获奖奖项 int prizeIndex = (360 - currentAngle) / (360 / prizes.length); prizeIndex = prizeIndex % prizes.length; JOptionPane.showMessageDialog( LuckyDrawWheel.this, "恭喜您获得: " + prizes[prizeIndex] ); } catch (InterruptedException e) { e.printStackTrace(); } finally { isSpinning = false; startButton.setEnabled(true); } }).start(); } public static void main(String[] args) { SwingUtilities.invokeLater(() -> new LuckyDrawWheel().setVisible(true)); } } 让文字旋转方向与扇形一致
最新发布
06-25
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值