Codeforces #560 (Div. 3)--D E 假設思想/區間重疊貢獻次數

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

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章