[題解]2018湘潭邀請賽
A.Easy h-index
題目描述
The h-index of an author is the largest h where he has at least h papers with citations not less than h.Bobo has published many papers. Given a0, a1, a2 ,..., an which means Bobo has published a i papers with citations exactly i , ?nd the h-index of Bobo.
輸入
The input consists of several test cases and is terminated by end-of-file.輸出
For each test case, print an integer which denotes the result.• 1 ≤ n ≤ 2 · 105
• 0 ≤ ai ≤ 109
• The sum of n does not exceed 250,000.
樣例輸入
1
1 2
2
1 2 3
3
0 0 0 0
樣例輸出
1 2 0
題意:給定被引用次數為0~n的論文分別有幾張,找到最大的h,滿足被引用次數大於等於h的論文至少有h張
思路:在區間[0,n]內二分答案;或直接從n~0遍歷找到第一個滿足條件的h
AC代碼:
#include <iostream> #include<cstdio> #include<algorithm> typedef long long ll; using namespace std; ll n; ll a[200010]; bool ok(ll x){ ll cntView Code=0;//cnt的值可能會爆int for(ll i=0;i<=n;i++) if(i>=x) cnt+=a[i]; if(cnt>=x) return true; return false; } int main() { while(cin>>n){ for(ll i=0;i<=n;i++){ cin>>a[i]; } ll l=0,r=n; while(l<=r){ ll mid=(l+r)/2; if(ok(mid)) l=mid+1; else r=mid-1; } cout<<r<<endl; } return 0; }
B.Higher h-index
題目描述
The h-index of an author is the largest h where he has at least h papers with citations not less than h .Bobo has no papers and he is going to publish some subsequently. If he works on a paper for x hours, the paper will get (a·x ) citations from other other persons, where a is a known constant. It’s clear that x should be a positive integer.
There is also a trick – one can cite his own papers published earlier.
Given Bobo has n working hours, ?nd the maximum h-index of him.
輸入
The input consists of several test cases and is terminated by end-of-file.Each test case contains two integers n and a .
輸出
For each test case, print an integer which denotes the maximum h-index.• 1 ≤ n ≤ 109
• 0 ≤ a ≤ n
• The number of test cases does not exceed 104 .
樣例輸入
3 0
3 1
1000000000 1000000000
樣例輸出
1
2
1000000000
提示
For the ?rst sample, Bobo can work 3 papers for 1 hour each. With the trick mentioned, he will get papers with citations 2 , 1 , 0. Thus, his h-index is 1.
For the second sample, Bobo can work 2 papers for 1 and 2 hours respectively. He will get papers with citations 1 + 1 , 2 + 0. Thus, his h-index is 2.
題意:給定n個小時,可以用其中x(1<=x<=n)個小時寫一篇論文,那麽這篇論文的"既定"引用數將會是x*a(a為給定正整數);此外,已經寫好的論文將會被其後寫成的論文所引用,也就是說,這篇論文的總引用數將會是"既定"引用數+其後論文篇數;問在所有的寫論文方案中(例如一種方案就是用n個小時寫n篇論文,每篇論文各花1小時(可以得到這n篇論文的引用數)),h最大為多少(h的含義同上題)(每一種方案都對應著一個h,求這些h中的最大者)
思路:最優方案(即對應h值最大的方案)是平攤n小時寫成n篇論文(證明未知);此時n篇論文的引用數為a,a+1,a+2,...,a+n-1,引用數為a+i時,引用數大於等於它的論文有n-i篇,令a+i=n-i得i=(n-a)/2,所以h=a+(n-a)/2;
AC代碼:
#include<cstdio> int main(){ int n,a; while(scanf("%d%d",&n,&a)!=EOF){ printf("%d\n",a+(n-a)/2); } return 0; }View Code
C.Just h-index
D.Circular Coloring
E.From Tree to Graph
F.Sorting
題目描述
Bobo has n tuples ( a1 , b1 , c1 ) , ( a2 , b2 , c2 ) , . . . , ( an , bn , cn ). He would like to ?nd the lexicographically smallest permutation p1 , p2 , . . . , pn of 1 ,2 , . . . , n such that for i ∈ {2 , 3 , . . . , n} it holds that輸入
The input consists of several test cases and is terminated by end-of-file.The first line of each test case contains an integer n . The i-th of the following n lines contains 3 integers ai,bi and ci .
輸出
For each test case, print n integers p1, p2,..., pn seperated by spaces. DO NOT print trailing spaces.Constraint
• 1 ≤ n ≤ 103
• 1 ≤ ai , bi , ci ≤ 2 × 109
• The sum of n does not exceed 104 .
樣例輸入
2
1 1 1
1 1 2
2
1 1 2
1 1 1
3
1 3 1
2 2 1
3 1 1
樣例輸出
2 1
1 2
1 2 3
題意:給定n個元組(a1,b1,c1),(a2,b2,c2),...,(an,bn,cn),將其按(ai+bi)/(ai+bi+ci)的值從小到大排序,輸出排序後的n個元組的原序號;
思路:編寫sort裏的cmp函數(形參為元組結構體元素,設為Tuple x,Tuple y),若直接算出(x.a+x.b)*(y.a+y.b+y.c)和(y.a+y.b)*(x.a+x.b+x.c)再比較大小,這兩個結果會爆unsigned long long;
可以把因式乘積展開成多項式的和,約去兩式中相同的項,得到x.a*y.c+x.b*y.c和y.a*x.c+y.b*x.c,因此只需計算它倆再比較即可,結果不會爆unsigned long long
AC代碼:
#pragma GCC optimize(2) #include<iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <set> using namespace std; struct Tuple{ long long a,b,c; int ind; }tup[100010]; bool cmp(Tuple x,Tuple y){ unsigned long long l=x.a*y.c+x.b*y.c; unsigned long long r=y.a*x.c+y.b*x.c; if(l==r) return x.ind<y.ind; return l<r; } int main(){ int n; while(scanf("%d",&n)!=EOF){ for(int i=1;i<=n;i++){ cin>>tup[i].a>>tup[i].b>>tup[i].c; tup[i].ind=i; } sort(tup+1,tup+1+n,cmp); for(int i=1;i<=n;i++){ if(i!=1) printf(" "); cout<<tup[i].ind; } printf("\n"); } return 0; }View Code
G.String Transformation
題目描述
Bobo has a string S = s1 s2...sn consists of letter a , b and c . He can transform the string by inserting or deleting substrings aa , bb and abab .Formally, A = u ? w ? v (“ ? ” denotes string concatenation) can be transformed into A 0 = u ? v and vice versa where u , v are (possibly empty) strings and w ∈ { aa , bb , abab } .
Given the target string T = t1 t2 . . . tm , determine if Bobo can transform the string S into T .
輸入
The input consists of several test cases and is terminated by end-of-file.The first line of each test case contains a string s1 s2 ...sn . The second line contains a string t1 t2 . . . tm .
輸出
For each test case, print Yes if Bobo can. Print No otherwise.• 1 ≤ n, m ≤ 104
• s1 , s2 ,..., sn , t1 , t2 , . . . , tm ∈ { a , b , c }
• The sum of n and m does not exceed 250,000.
樣例輸入
ab
ba
ac
ca
a
ab
樣例輸出
Yes
No
No
提示
For the first sample, Bobo can transform as ab => aababb => babb => ba .
題意:給定字符串S和T(均只由a,b,c三個字母組成),可對S進行插入或刪除操作(插入或刪除的子串只能是"aa","bb"或"abab"),問能否通過操作將S變為T
思路:發現經過操作一定可將ab—>ba、ba—>ab(等價於相鄰的ab可以互換位置),那麽我們以c為分隔點將S劃分為若幹小段,對每一個小段,一定可以通過互換相鄰a,b的操作使a全在一邊,b全在一邊,兩兩約去a,兩兩約去b,得到“化簡”後的小段(可能其中有一個"ab"或有一個‘a‘或有一個‘b‘或為空);就這樣分別將每一個小段都“化簡”,而原來c的位置不動,得到整個化簡後的S;對T進行同樣的“化簡”操作;若化簡後的S,T相同,則Yes,否則No
AC代碼:
#include <iostream> #include<cstdio> #include<cstring> using namespace std; char s1[1000010]; char s2[1000010]; char tmp1[1000010]; char tmp2[1000010]; int main() { while(scanf("%s%s",s1,s2)!=EOF){ int len=strlen(s1); int cnt_1=0,cnt_2=0; int cnt_a=0,cnt_b=0; for(int i=0;i<len;i++){ if(s1[i]==‘c‘) { if(cnt_a%2==0&&cnt_b%2==0) ; else if(cnt_a%2==1&&cnt_b%2==0) tmp1[++cnt_1]=‘a‘; else if(cnt_a%2==0&&cnt_b%2==1) tmp1[++cnt_1]=‘b‘; else {tmp1[++cnt_1]=‘a‘; tmp1[++cnt_1]=‘b‘;} tmp1[++cnt_1]=‘c‘; cnt_a=0; cnt_b=0; } else if(s1[i]==‘a‘) cnt_a++; else cnt_b++; } if(cnt_a%2==0&&cnt_b%2==0) ; else if(cnt_a%2==1&&cnt_b%2==0) tmp1[++cnt_1]=‘a‘; else if(cnt_a%2==0&&cnt_b%2==1) tmp1[++cnt_1]=‘b‘; else {tmp1[++cnt_1]=‘a‘; tmp1[++cnt_1]=‘b‘;} cnt_a=0; cnt_b=0; len=strlen(s2); for(int i=0;i<len;i++){ if(s2[i]==‘c‘) { if(cnt_a%2==0&&cnt_b%2==0) ; else if(cnt_a%2==1&&cnt_b%2==0) tmp2[++cnt_2]=‘a‘; else if(cnt_a%2==0&&cnt_b%2==1) tmp2[++cnt_2]=‘b‘; else {tmp2[++cnt_2]=‘a‘; tmp2[++cnt_2]=‘b‘;} tmp2[++cnt_2]=‘c‘; cnt_a=0; cnt_b=0; } else if(s2[i]==‘a‘) cnt_a++; else cnt_b++; } if(cnt_a%2==0&&cnt_b%2==0) ; else if(cnt_a%2==1&&cnt_b%2==0) tmp2[++cnt_2]=‘a‘; else if(cnt_a%2==0&&cnt_b%2==1) tmp2[++cnt_2]=‘b‘; else {tmp2[++cnt_2]=‘a‘; tmp2[++cnt_2]=‘b‘;} cnt_a=0; cnt_b=0; if(cnt_1!=cnt_2) printf("No\n"); else{ int flag=0; for(int i=1;i<=cnt_1;i++){ if(tmp1[i]!=tmp2[i]) {flag=1;break;} } if(flag) printf("No\n"); else printf("Yes\n"); } } return 0; }View Code
H.Infinity
I.Longest Increasing Subsequence
J.Vertex Cover
K.2018
題目描述
Given a, b, c, d , find out the number of pairs of integers ( x, y ) where a ≤ x ≤ b, c ≤ y ≤ d and x · y is a multiple of 2018.輸入
The input consists of several test cases and is terminated by end-of-file.Each test case contains four integers a, b, c, d
輸出
For each test case, print an integer which denotes the result.• 1 ≤ a ≤ b ≤ 109 , 1 ≤ c ≤ d ≤ 109
• The number of tests cases does not exceed 104 .
樣例輸入
1 2 1 2018
1 2018 1 2018
1 1000000000 1 1000000000
樣例輸出
3
6051
1485883320325200
題意:給定區間[a,b]、[c,d],問有多少對有序數組(x,y)(x∈[a,b],y∈[c,d])使得x*y是2018的倍數
思路:2018=2*1009(分解質因數),則對x分類討論:1)僅為2的倍數;2)僅為1009的倍數;3)即為2又為1009的倍數;4)既不為2又不為1009的倍數
等價於如下分類討論:
1.若x是偶數:1)若x是1009的倍數,則y可為[c,d]中任意數; 2)若x不是1009的倍數,則y必定為[c,d]中1009的倍數
2.若x是奇數:1)若x是1009的倍數,則y必定為[c,d]中2的倍數; 2)若x不是1009的倍數,則y必定為[c,d]中2018的倍數
AC代碼:
#include<cstdio> #include<iostream> typedef unsigned long long ll; using namespace std; int main(){ ll a,b,c,d; while(cin>>a>>b>>c>>d){ ll num1_all_1009=b/1009-(a-1)/1009; ll num1_even=b/2-(a-1)/2; ll num1_1009_in_even=b/2018-(a-1)/2018; ll num1_rest_in_even=num1_even-num1_1009_in_even; ll num1_odd=(b-a+1)-num1_even; ll num1_1009_in_odd=num1_all_1009-num1_1009_in_even; ll num1_rest_in_odd=num1_odd-num1_1009_in_odd; ll ans=0; ans+=num1_1009_in_even*(d-c+1); ll num2_all_1009=d/1009-(c-1)/1009; ans+=num1_rest_in_even*num2_all_1009; ll num2_even=d/2-(c-1)/2; ans+=num1_1009_in_odd*num2_even; ll num2_all_2018=d/2018-(c-1)/2018; ans+=num1_rest_in_odd*num2_all_2018; cout<<ans<<endl; } return 0; }View Code
[題解]2018湘潭邀請賽