A注意下标 B排序扫一遍 C 贪心,以为是O(N^2)其实O(N)
D Almost All Divisors
题意:输入一堆数,看是否能找到一个数的所有因子(不包括1和它本身)包含所有输入的数
思路:
分解因子,但要分解那个数呢?有个小思想注意下。
假设思想:
假设输入的就是某个数的所有因子,则这个数取最小的话,一定 等于最小因子*最大因子(易得)
再将这个数分解因子,与原来比较即可
小Tips:
①开long long,防止相乘爆ll
②vector可以==比较,很好用
#include <bits/stdc++.h>
#pragma GCC optimize("O3")
#define int long long
using namespace std;
typedef pair<int, int> PII;
typedef vector<PII> VII;
typedef long long LL;
int t, n;
vector<int> d;
void test() {
int n = d[0]*d.back();
vector<int> v;
v.clear();
for (int i = 2; i*i <= n; ++i)
if (n%i == 0) {
v.push_back(i);
if (i*i != n)
v.push_back(n/i);
}
sort(v.begin(), v.end());
if (v == d)
cout<<n<<"\n";
else
cout<<"-1\n";
}
signed main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
cin >> t;
while (t--) {
cin >> n;
d.clear();
for (int i = 0; i < n; ++i) {
int x;
cin >> x;
d.push_back(x);
}
sort(d.begin(), d.end());
test();
}
return 0;
}
E.Two Arrays and Sum of Functions
题意:b数组可以排序,求每个区间对应下标a数组和b数组的乘积和
思路:
显然两个数差越大,乘积越小,比如1*5小于3*3
因此一个序列从小到大排序,另一个序列从大到小排序的时候得到乘积和最小
但是注意由于多个区间重叠,我们只需要计算每个“位置”的贡献。包含第i个位置的左端点l有i种取法,右端点有(n-i+1)种(可能l==r),每个位置总共重复i*(n-i+1)次
这样把a[i]*i*(n-i+1)从小到大排序,b[i]从大到小排序,对应位置乘积再求和,可以算出结果
拓展:因为a不能排序,实际上b数组不一定是从大到小排序,而是对号入座(小对大,大对小),如果找到b数组移动后的位置,要多用个结构体存a的初始下标
细节:取模若写个+=,加完还要取模
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll mod=998244353;
ll a[300005],b[300005];
bool cmp(int x,int y){
return x>y;
}
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
a[i]*=(ll)(i)*(ll)(n-i+1);//乘上再比
}
for(int i=1;i<=n;i++){
scanf("%lld",&b[i]);
}
sort(a+1,a+1+n);
sort(b+1,b+1+n,cmp);
ll sum=0;
for(int i=1;i<=n;i++){
sum=(sum+a[i]%mod*b[i]%mod)%mod;
}
cout<<sum<<endl;
}