1541B
已知i和a[i]的情况下,要是i+j=a[i]*a[j],只需要使j满足i+j是a[i]的倍数
推导
(
i
+
j
)
(i+j)
(i+j)%
a
[
i
]
=
0
a[i]=0
a[i]=0
i
i
i%
a
[
i
]
+
j
a[i]+j
a[i]+j%
a
[
i
]
=
a
[
i
]
a[i]=a[i]
a[i]=a[i]
j
j
j%
a
[
i
]
=
a
[
i
]
−
i
a[i]=a[i]-i
a[i]=a[i]−i%
a
[
i
]
;
a[i];
a[i];
const int N=200010;
int a[N];
int main() {
IOS;
int t;
cin>>t;
while(t--){
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
ll cnt=0;
for(int i=1;i<=n;i++){
for(int j=a[i]-i%a[i];j<i;j+=a[i]){
if(a[i]*a[j]==i+j) cnt++;
}
}
cout<<cnt<<endl;
}
return 0;
}
1541C
思路:根据原来给定的数字,先排序,就可以得到已知地图的所有边权的最小和,然后每两个点之间可以加一条权值为负数的边,使这个值恰好是对应正数的和,这样既不会影响牛从1号点到其他点的距离(因为一次循环到1号点的距离是0,要走其他点的位置,仍然需要题中给定的距离);
推导
设数组p是a的差分数组,s表示每个点到1号点所有的负边权的和;
d表示距离
1:
s
[
1
]
=
p
[
1
]
;
s[1]=p[1];
s[1]=p[1];
2:
s
[
2
]
=
s[2]=
s[2]=
d
(
2
1
)
d(2~1)
d(2 1)
3:
s
[
3
]
=
s[3]=
s[3]=
d
(
3
2
)
d(3~2)
d(3 2),
d
(
3
1
)
d(3~1)
d(3 1)
4:
s
[
4
]
=
s[4]=
s[4]=
d
(
4
3
)
d(4~3)
d(4 3)
,
d
(
4
2
)
,d(4~2)
,d(4 2)
,
d
(
4
1
)
,d(4~1)
,d(4 1)
可以发现一个规律;
s
[
i
]
=
p
[
i
]
∗
(
i
−
1
)
+
s
[
i
−
1
]
s[i]=p[i]*(i-1)+s[i-1]
s[i]=p[i]∗(i−1)+s[i−1]
然后把每个s累加,用每个p累加的值减去s累加的值就是结果;
const int N = 100010;
ll a[N];
ll p[N];
ll s[N];
int main() {
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
ll ans = 0;
for (int i = 1; i <= n; i++) cin >> a[i];
sort(a + 1, a + 1 + n);
for (int i = 1; i <= n; i++) {
p[i] = a[i] - a[i - 1];
ans += p[i];
}
ll sum = 0;
for (int i = 1; i <= n; i++) {
s[i] = p[i] * (i - 1) + s[i - 1];
sum += s[i];
}
cout << ans - sum << endl;
}
return 0;
}
附加:
进制转换:
10进制转化为k进制;
循环型:
void fun1(ll x,int k){
for(int j=0;x;x/=k,j++){
st1[j]=x%k;
}
}
dfs型:
void fun(ll a,ll x,int k){//a是初始十进制的值;k表示k进制;
if(x==0) return ;
ll res=1;
int cnt=0;
while(res<=x) res*=k,cnt++;
cnt--,res/=k;
fun(x-res,k);
st[cnt]=(a/res)%k;
}