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

本文解析了五道算法竞赛题目,包括寻找符合条件的好对、判断序列操作的可能性、使数组元素相等的操作、寻找特定形式的表达式以及构造树的权重等。通过对每道题目的深入分析,提供了详细的解题思路和实现代码。

A Good Pairs

You are given an array a1,a2,…,ana_1,a_2,…,a_na1,a2,,an of positive integers. A good pair is a pair of indices (i,j)(i,j)(i,j) with 1≤i,j≤n1≤i,j≤n1i,jn such that, for all 1≤k≤n1≤k≤n1kn, the following equality holds:
∣ai−ak∣+∣ak−aj∣=∣ai−aj∣|ai−ak|+|ak−aj|=|ai−aj|aiak+akaj=aiaj
where ∣x∣|x|x denotes the absolute value of xxx.

Find a good pair. Note that iii can be equal to jjj.

#include<bits/stdc++.h> 
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,0x3f,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define MEMx(a,b) memset(a,b,sizeof(a));
#define INF (0x3f3f3f3f)
#define F (1000000007)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case #%d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
						For(j,m-1) cout<<a[i][j]<<' ';\
						cout<<a[i][m]<<endl; \
						} 
#pragma comment(linker, "/STACK:102400000,102400000")
#define ALL(x) (x).begin(),(x).end()
#define gmax(a,b) a=max(a,b);
#define gmin(a,b) a=min(a,b);
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return ((a-b)%F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
inline int read()
{
	int x=0,f=1; char ch=getchar();
	while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
	while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
	return x*f;
} 
pair<int,int> a[112345];
int main()
{
//	freopen("A.in","r",stdin);
//	freopen(".out","w",stdout);
	int T=read();
	while(T--) {
		int n=read();
		For(i,n) a[i]=mp(read(),i);
		sort(a+1,a+1+n);
		cout<<a[1].se<<' '<<a[n].se<<endl;
	}
	
	
	return 0;
}

B Subtract Operation

You are given a list of n integers. You can perform the following operation: you choose an element x from the list, erase x from the list, and subtract the value of x from all the remaining elements. Thus, in one operation, the length of the list is decreased by exactly 1.

Given an integer k (k>0), find if there is some sequence of n−1 operations such that, after applying the operations, the only remaining element of the list is equal to k.

#include<bits/stdc++.h> 
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,0x3f,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define MEMx(a,b) memset(a,b,sizeof(a));
#define INF (0x3f3f3f3f)
#define F (1000000007)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case #%d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
						For(j,m-1) cout<<a[i][j]<<' ';\
						cout<<a[i][m]<<endl; \
						} 
#pragma comment(linker, "/STACK:102400000,102400000")
#define ALL(x) (x).begin(),(x).end()
#define gmax(a,b) a=max(a,b);
#define gmin(a,b) a=min(a,b);
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return ((a-b)%F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
inline int read()
{
	int x=0,f=1; char ch=getchar();
	while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
	while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
	return x*f;
} 
set<ll> h;
int work() {
	ll n=read(),k=read();
	h.clear();
	bool b=0;
	while(n--) {
		ll a=read();
        if ( h.find(a-k)!=h.end() || h.find(a+k)!=h.end() ) {
        	b=1;
        };
        h.insert(a);
    }
    return b;
}
int main()
{
//	freopen("A.in","r",stdin);
//	freopen(".out","w",stdout);
	int T=read();
	while(T--) {
        puts(work()?"YES":"NO");
	}
	return 0;
}

C Make Equal With Mod

You are given an array of n non-negative integers a1,a2,…,an. You can make the following operation: choose an integer x≥2 and replace each number of the array by the remainder when dividing that number by x, that is, for all 1≤i≤n set ai to aimodx.

Determine if it is possible to make all the elements of the array equal by applying the operation zero or more times.

考虑ai mod ai=0a_i \bmod a_i =0aimodai=0,所以想办法把所有数变成0,发现有1的情况不行,1不能变成其它数

分类讨论:

  1. 没有1,全变成0
  2. 有1,全变成1
    情况2需要ai mod (ai−1)=1a_i \bmod (a_i-1) =1aimod(ai1)=1,因此不能出现相邻的数,不能出现0,20,20,2
#include<bits/stdc++.h> 
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,0x3f,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define MEMx(a,b) memset(a,b,sizeof(a));
#define INF (0x3f3f3f3f)
#define F (1000000007)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case #%d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
						For(j,m-1) cout<<a[i][j]<<' ';\
						cout<<a[i][m]<<endl; \
						} 
#pragma comment(linker, "/STACK:102400000,102400000")
#define ALL(x) (x).begin(),(x).end()
#define gmax(a,b) a=max(a,b);
#define gmin(a,b) a=min(a,b);
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return ((a-b)%F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
inline int read()
{
	int x=0,f=1; char ch=getchar();
	while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
	while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
	return x*f;
} 
int a[112345];
void work() {
		int n=read();
	For(i,n) a[i]=read();
	sort(a+1,a+1+n);
	int fl1=0;
	For(i,n) if(a[i]==1) fl1++;
	if(!fl1) puts("YES");
	else {
		For(i,n)
		if(a[i]==0||a[i]==2||(a[i]>=3&&i<n && a[i+1]==a[i]+1)) {
			puts("NO");
			return;
		}
		puts("YES");
	}
}
int main()
{
//	freopen("A.in","r",stdin);
//	freopen(".out","w",stdout);
	int T=read();
	while(T--) {
		work();
	}
	
	
	return 0;
}

D K-good

We say that a positive integer n is k-good for some positive integer k if n can be expressed as a sum of k positive integers which give k distinct remainders when divided by k.

Given a positive integer n, find some k≥2 so that n is k-good or tell that such a k does not exist.

k+(k+1)+⋯+(k+k−1)+tk=k(k−1)/2+tk(t≥0,t∈Z)k+(k+1)+\cdots + (k+k-1)+tk=k(k-1)/2+tk(t\ge 0,t\in Z)k+(k+1)++(k+k1)+tk=k(k1)/2+tk(t0,tZ)
因此当k是奇数时,k是n的因子
k是偶数的情况可以覆盖所有>=3的奇数的情况

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef long long ll;
const int maxp = 1e6 + 1, maxv = 25, maxc = (int)1e4 + 1;
int ptot, pr[maxp], d[maxp], cnt;
LL n, p[maxc];
LL mod_add(LL x, LL y, LL p) {
	return (x += y) < p ? x : x - p;
}
LL mod_mul(LL x, LL y, LL p) {
	LL ret = x * y - (LL)((long double)x * y / p + 0.5) * p;
	return ret < 0 ? ret + p : ret;
}
LL mod_pow(LL x, LL k, LL p) {
	LL ret = 1 % p;
	for( ; k > 0; k >>= 1, x = mod_mul(x, x, p))
		(k & 1) && (ret = mod_mul(ret, x, p));
	return ret;
}
bool miller_rabin(LL n) {
	if(n == 2) return 1;
	if(n < 2 || !(n & 1))
		return 0;
	LL s = 0, r = n - 1;
	for( ; !(r & 1); r >>= 1, ++s);
	for(int i = 0; pr[i] < n && pr[i] < maxv; ++i) {
		LL cur = mod_pow(pr[i], r, n), nxt;
		for(int j = 0; j < s; ++j) {
			nxt = mod_mul(cur, cur, n);
			if(nxt == 1 && cur != 1 && cur != n - 1) return 0;
			cur = nxt;
		}
		if(cur != 1) return 0;
	}
	return 1;
}
LL gcd(LL a, LL b) {
	int ret = 0;
	while(a) {
		for( ; !(a & 1) && !(b & 1); ++ret, a >>= 1, b >>= 1);
		for( ; !(a & 1); a >>= 1);
		for( ; !(b & 1); b >>= 1);
		if(a < b)
			swap(a, b);
		a -= b;
	}
	return b << ret;
}
LL pollard_rho(LL n) {
	static LL seq[maxp];
	while(1) {
		LL x = rand() % n, y = x, c = rand() % n;
		LL *px = seq, *py = seq, tim = 0, prd = 1;
		while(1) {
			*py++ = y = mod_add(mod_mul(y, y, n), c, n);
			*py++ = y = mod_add(mod_mul(y, y, n), c, n);
			if((x = *px++) == y) break;
			LL tmp = prd;
			prd = mod_mul(prd, abs(y - x), n);
			if(!prd) return gcd(tmp, n);
			if((++tim) == maxv) {
				if((prd = gcd(prd, n)) > 1 && prd < n) return prd;
				tim = 0;
			}
		}
		if(tim && (prd = gcd(prd, n)) > 1 && prd < n) return prd;
	}
}
void decompose(LL n) {
	for(int i = 0; i < cnt; ++i)
		if(n % p[i] == 0) {
			p[cnt++] = p[i];
			n /= p[i];
		}
	if(n < maxp) {
		for( ; n > 1; p[cnt++] = d[n], n /= d[n]);
	} else if(miller_rabin(n)) {
		p[cnt++] = n;
	} else {
		LL fact = pollard_rho(n);
		decompose(fact), decompose(n / fact);
	}
} // prepare pr(prime) and d(minimal factor)
map<LL,int> h;
ll xs[3000];
ll xs2[3000];
vector<vector<LL> > table;
int main() {
	for(int i = 2; i < maxp; ++i) {
		if(!d[i])
			pr[ptot++] = d[i] = i;
		for(int j = 0, k; (k = i * pr[j]) < maxp; ++j) {
			d[k] = pr[j];
			if(d[i] == pr[j])
				break;
		}
	}
	int m, mod = 1000000007;
	int T;cin>>T;
	while(T--) {
		cnt=0;
		LL n;
		cin>>n;
		LL n2=n;
		LL b = n;
		int a = 0;
		LL pa = 1;
	    while ((b & 1) == 0) {
	        b /= 2;
			pa *= 2;
	    }
	    pa *= 2;
	    if (pa + 1 <= b) {
			cout<<pa<<endl; continue;
		}
		decompose(n);
		sort(p, p + cnt);
		ll ans=-1;
		for(int i=0;i<cnt;i++) if(p[i]!=2){
			bool fl=2.0*n2/p[i]>=(p[i]-1);
			if (fl) {
				ans=p[i];break;
			}
		}
		cout<<ans<<endl;
	}
	return 0;
}

E Equal Tree Sums

You are given an undirected unrooted tree, i.e. a connected undirected graph without cycles.

You must assign a nonzero integer weight to each vertex so that the following is satisfied: if any vertex of the tree is removed, then each of the remaining connected components has the same sum of weights in its vertices.

 #include<bits/stdc++.h> 
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i>0;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,0x3f,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define MEMx(a,b) memset(a,b,sizeof(a));
#define INF (0x3f3f3f3f)
#define F (1000000007)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,cal) printf("Case #%d: %lld\n",kcase,cal);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
						For(j,m-1) cout<<a[i][j]<<' ';\
						cout<<a[i][m]<<endl; \
						} 
#pragma comment(linker, "/STACK:102400000,102400000")
#define ALL(x) (x).begin(),(x).end()
#define gmax(a,b) a=max(a,b);
#define gmin(a,b) a=min(a,b);
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
#define add(a,b) ((a+b)%F)
ll mul(ll a,ll b){return (a*b)%F;}
inline int read()
{
	int x=0,f=1; char ch=getchar();
	while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
	while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
	return x*f;
} 

#define MAXN (212345)
ll n;
vi v[MAXN];
int ans[MAXN];
void dfs(int x,int fa,int fl) {
	ans[x]=v[x].size();
	if(fl)ans[x]*=-1;
	for (auto u:v[x])
		if (u!=fa) {
			dfs(u,x,fl^1);
	}
}
int main()
{
//	freopen("c.in","r",stdin);
//	freopen(".out",w",stdout);
	int T=read();
	while(T--) {
		n=read();
		For(i,n-1) {
			int x=read(),y=read();
			v[x].pb(y); v[y].pb(x);
		}
		dfs(1,-1,1);
		For(i,n) v[i].resize(0);
		PRi(ans,n)
	}
	return 0;
}


F Parametric MST

You are given nnn integers a1,a2,…,ana1,a2,…,ana1,a2,,an. For any real number t, consider the complete weighted graph on nnn vertices Kn(t)Kn(t)Kn(t) with weight of the edge between vertices iii and jjj equal to wij(t)=ai⋅aj+t⋅(ai+aj)w_{ij}(t)=a_i⋅a_j+t⋅(a_i+a_j)wij(t)=aiaj+t(ai+aj).

Let f(t)f(t)f(t) be the cost of the minimum spanning tree of Kn(t)Kn(t)Kn(t). Determine whether f(t)f(t)f(t) is bounded above and, if so, output the maximum value it attains.

Input
The input consists of multiple test cases. The first line contains a single integer T(1≤T≤104)T (1≤T≤10^4)T(1T104) — the number of test cases. Description of the test cases follows.

The first line of each test case contains an integer n(2≤n≤2⋅105)n (2≤n≤2⋅10^5)n(2n2105) — the number of vertices of the graph.

The second line of each test case contains nnn integers a1,a2,…,an(−106≤ai≤106)a_1,a_2,…,a_n (−10^6 ≤ai≤ 10^6)a1,a2,,an(106ai106).

The sum of n for all test cases is at most 2⋅1052⋅10^52105.

Output
For each test case, print a single line with the maximum value of f(t)f(t)f(t) (it can be shown that it is an integer), or INF if f(t)f(t)f(t) is not bounded above.

Example
inputCopy
5
2
1 0
2
-1 1
3
1 -1 -2
3
3 -1 -2
4
1 2 3 -4
outputCopy
INF
-1
INF
-6
-18

w(i,j)=wij(t)=ai⋅aj+t⋅(ai+aj)=(ai+t)(aj+t)−t2w(i,j)=w_{ij}(t)=a_i⋅a_j+t⋅(a_i+a_j) = (a_i+t)(a_j+t)-t^2w(i,j)=wij(t)=aiaj+t(ai+aj)=(ai+t)(aj+t)t2
考虑最小生成树,对于点iii而言,当ai+t<0a_i+t<0ai+t<0时连aj+ta_j+taj+t最大的,当ai+t>0a_i+t>0ai+t>0时连aj+ta_j+taj+t最小的,当ai+t=0a_i+t=0ai+t=0时连任意一个。

最后考察当ttt为正、负无穷时,最小生成树边权和是否为正无穷即可。

 #include<bits/stdc++.h> 
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i>0;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,0x3f,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define MEMx(a,b) memset(a,b,sizeof(a));
#define INF (0x3f3f3f3f)
#define F (1000000007)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,cal) printf("Case #%d: %lld\n",kcase,cal);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
						For(j,m-1) cout<<a[i][j]<<' ';\
						cout<<a[i][m]<<endl; \
						} 
#pragma comment(linker, "/STACK:102400000,102400000")
#define ALL(x) (x).begin(),(x).end()
#define gmax(a,b) a=max(a,b);
#define gmin(a,b) a=min(a,b);
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
#define add(a,b) ((a+b)%F)
ll mul(ll a,ll b){return (a*b)%F;}
inline int read()
{
	int x=0,f=1; char ch=getchar();
	while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
	while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
	return x*f;
} 

#define MAXN (212345)
ll n;
ll a[MAXN];
bool fl=0;
ll work() {
	ll ans=-1e18;
	sort(a+1,a+1+n);
	ll B=0,K=0;
	Fork(i,2,n) K+=a[1]+a[i];
	if(K>0){ // means no upbound when t=+oo
		fl=1;return 0;
	} 
	K=0;
	For(i,n-1) K+=a[i]+a[n];
	if(K<0) {// means no upbound when t=-oo
		fl=1;return 0;
	}
	
	K=0;	
	Fork(i,2,n) K+=a[1]+a[i],B+=a[1]*a[i];
	// 1-n 2-n k-n 1-(k+1) 1-n-1
		
	gmax(ans,K*max(-a[1],-a[n])+B);
	
	Fork(i,2,n-1) {
		K+=-a[1]+a[n];B+=-a[1]*a[i]+a[i]*a[n];
		gmax(ans,K*(-a[i+1])+B);
		gmax(ans,K*(-a[i])+B);
	}
	return ans;	
}
int main()
{
//	freopen("c.in","r",stdin);
//	freopen(".out",w",stdout);
	int T=read();
	while(T--) {
		n=read();
		For(i,n) a[i]=read();
		fl=0;
		ll t=work();
		if(fl) puts("INF");else cout<<t<<endl;
	}
	return 0;
}


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
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值