codeforces 1541B &1541C

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](i1)+s[i1]
然后把每个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;
}
  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值