Codeforces Round #641 (Div. 2)


只寫了A~D

A - Orac and Factors

題意:f(n)就是n的第二小因數,問執行k次 n=f(n)+n 后的結果。

題解:如果一直找第二小的因子的話,1e9肯定得t。看下邊樣例解釋就會驚奇的發現,執行次數多了,n一定會變成2的倍數,然后就可以剪枝了。如果n不是2的倍數,那么就執行 n=f(n)+n,k-- 直到n是2的倍數(當然k得>0),最后再加上k*2。

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 
 5 int main()
 6 {
 7     ios::sync_with_stdio(false);
 8     cin.tie(0);
 9     cout.tie(0);
10     int t;
11     cin>>t;
12     while(t--){
13         ll n,k;
14         cin>>n>>k;
15         while(k){
16             if(n%2==0) break;
17             for(ll i=2;i<=n;i++){
18                 if(n%i==0){
19                     n+=i;
20                     break;
21                 }
22             }
23             k--;
24         }
25         n=n+k*2;
26         cout<<n<<endl;
27     }
28     return 0;
29 }

 

B - Orac and Models

題意:讓你找出一個序列使得他在原序列滿足一下條件 i%j==0&&a[i]>a[j]; 問最長的序列長度

題解:找1~n每個數當因子時最長的符合條件的序列。

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 
 5 ll a[100100];
 6 ll dp[100100];
 7 
 8 int main()
 9 {
10     ios::sync_with_stdio(false);
11     cin.tie(0);
12     cout.tie(0);
13     ll t;
14     cin>>t;
15     while(t--){
16         ll n;
17         cin>>n;
18         for(ll i=1;i<=n;i++) cin>>a[i];
19         ll ans=0 ;
20         for (ll i=n;i>=1;i--){
21             dp[i]=1;
22             for (ll j=i;j<=n;j+=i){
23                 if(a[j]>a[i])
24                     dp[i]=max(dp[i],dp[j]+1);
25             }
26             ans = max(dp[i],ans);
27         }
28         cout<<ans<<endl;
29     }
30     return 0;
31 }

 

C - Orac and LCM

題意:求這個序列所有數兩兩之間的 lcm 的 gcd。

題解:和a1 lcm 后的所有數的 gcd 就是lcm(a1,gcd(a2,a3, ......)),a2就是lcm(a2,gcd(a3,a4, ......)).....,然后再把這些數就行gcd

證明結論:

gcd( lcm (a,b), lcm(a,c) ) 

    = gcd( a*b/gcd(a,b), a*c/gcd(a,c) )  

    = a*gcd( b/gcd(a,b), c/gcd(a,c) );

lcm( a, gcd(b, c) )=a*gcd(b, c) / gcd(a,gcd(b, c));

 最大公約數的百度百科的性質那一欄也能找到這個結論。

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 
 5 ll a[100100];
 6 ll p[200100];
 7 
 8 int main()
 9 {
10     ios::sync_with_stdio(false);
11     cin.tie(0);
12     cout.tie(0);
13     ll n;
14     cin>>n;
15     for(ll i=1;i<=n;i++) cin>>a[i];
16     ll ans;
17     p[n]=a[n];
18     for(ll i=n-1;i>0;i--){
19         p[i]=__gcd(p[i+1],a[i]);
20     }
21     ans=a[1]*p[2]/__gcd(a[1],p[2]);
22     for(ll i=2;i<=n;i++){
23         ans=__gcd(ans,p[i+1]*a[i]/__gcd(a[i],p[i+1]));
24     }
25     cout<<ans<<endl;
26     return 0;
27 }

 

D - Orac and Medians

題意:數組里一段數可以都變成他的中位數,問整個序列能不能變成k。

題解:

①判斷一下序列里是否有k這個數,沒有的話就直接輸出no;

②如果整個序列 >=k 的個數比 <k 的個數多,就輸出yes;

③判斷一下序列里是否有一段長度>2的連續子序列使得 >=k 的個數比 <k 的個數多,有的話就輸出yes,沒有就輸出no;(代碼略丑)

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 
 5 int a[100100];
 6 int p[100100];
 7 
 8 int main()
 9 {
10     ios::sync_with_stdio(false);
11     cin.tie(0);
12     cout.tie(0);
13     int t;
14     cin>>t;
15     while(t--){
16         int n,k;
17         cin>>n>>k;
18         for(int i=1;i<=n;i++) cin>>a[i],p[i]=0;
19         int flag=0;
20         for(int i=1;i<=n;i++){
21             if(a[i]==k) flag=1;
22             if(a[i]>=k) p[i]=1;
23             else p[i]=-1;
24         }
25         if(!flag) {cout<<"no"<<endl;continue;}
26         flag=0;
27         for(int i=1;i<=n;i++){
28             p[i]+=p[i-1];
29         }
30         if(p[n]>0) flag=1;
31         int minn=p[0];
32         for(int i=2;i<=n;i++){
33             if(p[i]>minn){
34                 flag=1;
35                 break;
36             }
37             if(p[i-1]<minn){
38                 minn=p[i-1];
39             }
40         }
41         if(!flag) {cout<<"no"<<endl;continue;}
42         cout<<"yes"<<endl;
43     }
44     return 0;
45 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM