A - Right-Coupled Numbers
思路
暴力去试就通过了。
#include<bits/stdc++.h>
using namespace std;
int n;
void solve(){
scanf("%d",&n);
for(int i=1;i<=sqrt(n);i++){
if(n%i==0){
int a=i,b=n/i;
if(a>b) swap(a,b);
if(a*2>=b){
printf("1\n");
return ;
}
}
}
printf("0\n");
}
int main(){
int te;
scanf("%d",&te);
while(te--) solve();
}
G - August
思路
首先,这个图形左右对称,其次,上方图形为两个半圆。所以只需要计算右下方这块面积就可以了(计算左下方的也行)。
右下方的方程为
y
=
2
b
π
(
a
r
c
s
i
n
x
−
a
a
−
π
2
)
y=\frac{2b}{\pi}(arcsin\frac{x-a}{a}-\frac{\pi}{2})
y=π2b(arcsinax−a−2π),在
[
0
,
2
a
]
[0,2a]
[0,2a]积分,得
∫
0
2
a
2
b
π
(
a
r
c
s
i
n
x
−
a
a
−
π
2
)
=
2
b
π
∫
0
2
a
a
r
c
s
i
n
x
−
a
a
−
∫
0
2
a
b
\int^{2a}_0\frac{2b}{\pi}(arcsin\frac{x-a}{a}-\frac{\pi}{2})=\frac{2b}{\pi}\int^{2a}_0arcsin\frac{x-a}{a}-\int^{2a}_0b
∫02aπ2b(arcsinax−a−2π)=π2b∫02aarcsinax−a−∫02ab.
其中
∫
0
2
a
a
r
c
s
i
n
x
−
a
a
=
∫
−
1
1
a
r
c
s
i
n
x
=
0
\int^{2a}_0arcsin\frac{x-a}{a}=\int^1_{-1}arcsinx=0
∫02aarcsinax−a=∫−11arcsinx=0,所以面积为
2
a
b
2ab
2ab。
总面积为:
4
a
b
+
a
2
π
4ab+a^2\pi
4ab+a2π。
#include<bits/stdc++.h>
#define pi acos(-1)
using namespace std;
int a,b,te;
double ans=0,esp=1e-4;
void solve(){
scanf("%d%d",&a,&b);
ans=b*4*a;
ans+=a*a*pi;
printf("%f\n",ans);
}
int main(){
scanf("%d",&te);
while(te--) solve();
}
J - Goodbye
“Goodbye to the friends I’ve had, goodbye to my upstairs neighbor, goodbye to the kids downstairs, and anybody who lend me a favor.”
“Or, goodbye to the positive proper divisor?”
That game is popular these days. Two player take turns to choose a specific number and claim it. The player who takes the first turn chooses one positive proper divisor of given n. In the next rounds, player should choose one positive proper divisor (真因数) of the number claimed in the previous round. The player who can’t make a choice will win.
Formally, a positive proper divisor of n is a divisor of n, and it cannot be either 1 or n.
Now Chino is going to play this game with David. Chino always wants to win and meanwhile she wants to keep the chosen number as big as possible. If with the given n, Chino will win directly or fail anyway, you should also tell her.
Can you help Chino to choose her answer in the first round?
Input
The first line contains one integer T ( 1 ≤ T ≤ 1 0 3 ) T (1≤T≤10^3) T(1≤T≤103) denoting the count of testcases.
For each testcase, one line with one integer n ( 1 ≤ n ≤ 1 0 5 ) n (1≤n≤10^5) n(1≤n≤105) denoting the given n in one game.
Output
For each testcase, you should output the biggest choice, or 0 when Chino will win directly, or −1 when Chino will fail anyway.
Input
4
3
4
8
666
Output
0
-1
4
111
思路
对一个数进行质因数分解,设它有n个质因数(相同的因子出现多次的话,质因数数量也记录多次):
- 如果n==1,先手可以直接获胜。
- 如果n==2,先手必败。
- 其他情况,答案为最大的两个质因数之积。
#include<cstdio>
#include<cmath>
using namespace std;
int n,cnt,p[105];
void getPrime(int x){
cnt=0;
for(int i=2;i<=sqrt(x);i++)
while(x%i==0) p[cnt++]=i,x/=i;
if(x>1) p[cnt++]=x;
}
void solve(){
scanf("%d",&n);
getPrime(n);
if(cnt==1) puts("0");
else if(cnt==2) puts("-1");
else printf("%d\n",p[cnt-1]*p[cnt-2]);
}
int main(){
int te;
scanf("%d",&te);
while(te--) solve();
}
B - Make Numbers
题意
图片很模糊,题意为:输入四个小于10的整数,可以在数字之间添加 " + " , " − " , " ∗ " "+","-","*" "+","−","∗"三种符号,也可以交换数字顺序,或者把两个、三个数字组合为一个数字。问,这些表达式可以产生多少种非负的结果?
#include<cstdio>
#include<set>
#include<algorithm>
using namespace std;
int a[4],ans;
set<int> st;
void calc2(int a,int b){
st.insert(a+b); st.insert(a-b); st.insert(a*b);
}
void calc3(int a,int b,int c){
st.insert(a+b+c); st.insert(a+b-c); st.insert(a+b*c);
st.insert(a-b+c); st.insert(a-b-c); st.insert(a-b*c);
st.insert(a*b+c); st.insert(a*b-c); st.insert(a*b*c);
}
void calc4(int a,int b,int c,int d){
st.insert(a+b+c+d); st.insert(a+b+c-d); st.insert(a+b+c*d);
st.insert(a+b-c+d); st.insert(a+b-c-d); st.insert(a+b-c*d);
st.insert(a+b*c+d); st.insert(a+b*c-d); st.insert(a+b*c*d);
st.insert(a-b+c+d); st.insert(a-b+c-d); st.insert(a-b+c*d);
st.insert(a-b-c+d); st.insert(a-b-c-d); st.insert(a-b-c*d);
st.insert(a-b*c+d); st.insert(a-b*c-d); st.insert(a-b*c*d);
st.insert(a*b+c+d); st.insert(a*b+c-d); st.insert(a*b+c*d);
st.insert(a*b-c+d); st.insert(a*b-c-d); st.insert(a*b-c*d);
st.insert(a*b*c+d); st.insert(a*b*c-d); st.insert(a*b*c*d);
}
int main(){
for(int i=0;i<4;i++) scanf("%d",&a[i]);
sort(a,a+4);
do{
calc2(a[0],a[1]*100+a[2]*10+a[3]);
calc2(a[0]*10+a[1],a[2]*10+a[3]);
calc2(a[0]*100+a[1]*10+a[2],a[3]);
calc3(a[0],a[1],a[2]*10+a[3]);
calc3(a[0],a[1]*10+a[2],a[3]);
calc3(a[0]*10+a[1],a[2],a[3]);
calc4(a[0],a[1],a[2],a[3]);
}while(next_permutation(a,a+4));
for(int e : st) if(e>=0) ans++;
printf("%d",ans);
}
基本上照搬了别人的代码,每个
c
a
l
c
calc
calc函数只管当前顺序下的组合,不交换数字顺序。
c
a
l
c
calc
calc函数内部直接列举出所有的计算方法。
注意最后只统计答案非负的数量。
E - Optimization for UltraNet
思路
把原问题转为二分判定存在,就可以得到权值最小的边。之后建图,对于每条边,设它连接的两个结点分别为u和v,权值为w,则它对答案的贡献为 S i z e ( u ) × S i z e ( v ) × w Size(u)\times Size(v)\times w Size(u)×Size(v)×w, S i z e ( u ) Size(u) Size(u)代表u所在的连通分量的大小。从最小生成树的最短边开始,每次计算最短的边,计算之后删掉这条边。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=1e4+5,Emaxn=1e6+5;
struct N{int u,v,w;}e[Emaxn];
int head[maxn],ver[Emaxn],edge[Emaxn],Next[Emaxn],from[Emaxn],tot;
int n,m,fa[maxn],ans,vis[maxn],l,r;
void add(int u,int v,int w){ver[++tot]=v,edge[tot]=w,from[tot]=u,Next[tot]=head[u],head[u]=tot;}
int get(int x){return fa[x]==0?x:fa[x]=get(fa[x]);}
bool cmp(N &a,N &b){return a.w<b.w;}
bool judge(int mid,int build=0){
memset(fa,0,sizeof(fa));
int cnt=n;
for(int i=mid;i<m;i++){
int x=get(e[i].u),y=get(e[i].v);
if(x==y) continue;
if(build) add(e[i].u,e[i].v,e[i].w),add(e[i].v,e[i].u,e[i].w);
fa[x]=y; cnt--;
if(cnt==1) return true;
}
return cnt==1;
}
int getSize(int x,int v){
int ret=1; vis[x]=1;
for(int i=head[x];i;i=Next[i])
if(!vis[ver[i]]&&edge[i]>v) ret+=getSize(ver[i],v);
return ret;
}
signed main(){
scanf("%lld%lld",&n,&m);
for(int i=0;i<m;i++)
scanf("%lld%lld%lld",&e[i].u,&e[i].v,&e[i].w);
sort(e,e+m,cmp);
l=0,r=m-1;
while(l<r){
int mid=(l+r+1)/2;
if(judge(mid)) l=mid; else r=mid-1;
}
for(int i=1;i<=tot;i++){
memset(vis,0,sizeof(vis));
int a=getSize(from[i],edge[i]),b=getSize(ver[i],edge[i]);
ans+=a*b*edge[i];
}
printf("%lld\n",ans/2);
}