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;
}