catalogue
C. Number and continued fraction
A. Factor sum
I provide an idea similar to the Elsevier sieve. For example, there are four numbers 1, 2, 3 and 4, and the maximum is 4. We list the multiples of each number less than 4, then this multiple must contain the factor before multiplying the multiple. For example, if the quadruple of 1 is 4, then 4 must contain the factor of 1 We can open another array to record their sum. If we contain this factor, we add the factor to the corresponding position
#include<iostream> #define ll long long using namespace std; ll sum[1000006]; void init(int n) { for(int i=1;i<=n;i++) { for(int j=1;j*i<=n;j++) { sum[i*j]+=i; } } } int main() { int i,j,t,n; cin>>n; init(n); for(int i=1;i<=n;i++) cout<<sum[i]<<" "; cout<<endl; return 0; }
B. Find number
This problem is discussed in two cases. If the two digits are the same, for example, they are three digits, we can list its equation as f(x)=x*(999-x). At this time, we will find that this is a quadratic function with an opening downward. When taking the maximum value, it is 499 and 500. By analogy, we can draw a conclusion that the closer the number of the same digit is to the middle, the greater the value is, Then we can only compare the two numbers with the size 1 of the center distance If it is not an identical number, discuss the large number. 1. The answer is that the observation function takes the maximum value in its range
#include<iostream> #include<cmath> #define int long long using namespace std; int change(int x) { int wei=1,tran=0; int z=x; while(x) { tran+=wei*(9-x%10); wei*=10; x/=10; } return tran*z; } signed main() { int l,r,maxx=0,weil=0,weir=0,ll,rr,tt=4; scanf("%lld%lld",&l,&r); ll=l; rr=r; while(ll) { ll/=10; weil++; } while(rr) { rr/=10; weir++; } if(weir>weil) { tt=pow(10,weir)/2-1; if(r<tt) { printf("%lld",change(r)); } else { printf("%lld",change(tt)); } } else if(weir==weil) { tt=pow(10,weir)/2-1; if(l<tt&&r<=tt) { printf("%lld",change(r)); } else if(l<=tt&&r>=tt) { printf("%lld",change(tt)); } else if(l>tt&&r>tt) { printf("%lld",change(l)); } } return 0; }
C. Number and continued fraction
Pure simulation problem, first calculate the conversion method of these two by yourself, and then try to implement it in code. Pay attention to some special cases
For continued fraction to fraction, we use two variables to store numerator and denominator, so as to simulate its addition
There are many pits when converting fractions into continued fractions. Be sure to reduce the numerator denominator during the simulation. After the reduction, pay attention to whether these situations can be eliminated In addition, pay attention to the output results; And, the situation
#include<iostream> #include<algorithm> #include<string> #define int long long using namespace std; string str; int arr[500]; void change1() { int k,cnt1,cnt2,cnt3=1,id=0,temp=0; for(int i=1;i<str.size();i++) { if(str[i]>='0'&&str[i]<='9') { temp=temp*10+str[i]-'0'; } else { arr[id]=temp; temp=0; id++; } } if(id==1) { printf("%lld\n",arr[0]); return ; } cnt1=arr[id-1]; for(int i=id-2;i>=0;i--) { cnt2=arr[i]; cnt3=cnt2*cnt1+cnt3; k=cnt3; cnt3=cnt1; cnt1=k; } if(cnt3==1) { printf("%lld\n",cnt1); return; } printf("%lld/%lld\n",cnt1,cnt3); } void change2() { int k,temp=0,cnt1,cnt2,cnt3,id=0; for(int i=0;i<str.size();i++) { if(str[i]>='0'&&str[i]<='9') { temp=temp*10+str[i]-'0'; } else { cnt1=temp; temp=0; } } cnt2=temp; int gc=__gcd(cnt1,cnt2); cnt1/=gc; cnt2/=gc; printf("["); int ma=0; while(cnt1%cnt2!=1) { if(cnt1%cnt2==0) { printf("%lld]\n",cnt1/cnt2); return; } int gc=__gcd(cnt1,cnt2); cnt1/=gc; cnt2/=gc; printf("%lld",cnt1/cnt2); if(ma==0) printf(";"),ma=1; else printf(","); cnt1=cnt1%cnt2; k=cnt1; cnt1=cnt2; cnt2=k; } printf("%lld,%lld",cnt1/cnt2,cnt2); printf("]\n"); } signed main() { while(cin>>str) { if(str[0]=='[') change1(); else change2(); } return 0; }
D. File lookup
The method I use is dfs + double ended queue simulation stack (you don't have to use double ended queue. You only need something that can realize the storage mode of traversal and simulation stack. You can try array simulation. It is recommended to learn stl container) There are three variables in the title, folder, number of files and file name, so it should be noted that each time we input it, we judge whether it is a file name or a file. As mentioned in the title, the file name contains a ".", You can distinguish the two in turn, and then enter the number of files for recursion. Each time you recurse, use the double ended queue to save the current folder name. This is always the case until you traverse the file. Judge whether the file is the same as the given file to be found. If it is the same, traverse, and take out the folder name in the stack simulated by the double ended queue for output Then, when returning to the previous layer and returning to the previous layer for recursion, note that if you have exited this folder at this time, you should take the folder name out of the stack of double ended queue simulation
Analyze the sample
nanqiao.cpp nanqiao 2 ccsu 1 nanqiao.cpp nanqiao 1 ccsu.cpp
First, we entered nanqiao because it does not contain ".", Then save it into the stack of double ended queue simulation. After digital input, go to CCs. Because it is a folder, save it into the stack, and then recurse to the next layer. You will find that the next one is nanqiao cpp. Just output all the elements in the simulation stack
#include<iostream> #include<string> #include<deque> using namespace std; string str,ss; deque<string>sta; void dfs(int x) { string s1; int xx; while(x>0) { x--; cin>>s1; int mark=0; for(int i=0;i<s1.size();i++) { if(s1[i]=='.') { mark=1; } } if(mark==1) { if(s1==str) { for(int j=0;j<sta.size();j++) { cout<<sta[j]<<"\\"; } cout<<s1<<endl; } } else { sta.push_back(s1); cin>>xx; dfs(xx); sta.pop_back(); } } return ; } int main() { int t; cin>>str; while(cin>>ss) { int mark=0; for(int i=0;i<ss.size();i++) { if(ss[i]=='.') { mark=1; } } if(mark==1) { if(ss==str) cout<<ss<<endl; } else { sta.push_back(ss); cin>>t; dfs(t); sta.pop_back(); } } return 0; }
E. Dominoes
There are many ways to solve this problem. The common ones are bfs and simulation. I use the simulation method
Because there are only two kinds of dominoes that will change the shape of other dominoes: "\" "/" Let's enumerate all the combinations of the two cases for processing First, traverse the string. When the traversed character is not "|" at this time, use L (left end) and R (right end) to record the left and right end forms of the first two traversed, and then process them section by section. For example, if it is "/" \ ", the cards in the middle will fall to the middle. I use an interval here, If the number of cards in this interval is odd, one card will remain in the "|" state After dealing with the situation of these cards, use L (left end) to record the subscript and form of R (right end) at this time (R (right end) at this time will have an effect with the first non "|" card behind) After such a series of handling, we should also pay attention If the first non "|" domino traversed from the left is "\", it will become "\" from the beginning to this card. Similarly, if the last non "|" is "/", it will also affect the last situation of this card
Then there is the escape character, '\ \' can represent \
#include<iostream> #include<cstring> using namespace std; struct node { char ty; int idx; }l,r; char str[10000007]; int main() { scanf("%s",str); int len=strlen(str); int cnt=0; for(int i=0;i<len;i++) { if(str[i]!='|'&&cnt==0) { l.ty=str[i]; l.idx=i; cnt=1; } else if(str[i]!='|'&&cnt==1) { r.ty=str[i]; r.idx=i; cnt=2; } if(cnt==2) { if(l.ty=='/'&&r.ty=='/') { for(int j=l.idx;j<=r.idx;j++) str[j]='/'; l=r; cnt=1; } else if(l.ty=='/'&&r.ty=='\\') { int ll=r.idx-l.idx-1; ll/=2; for(int j=l.idx;j<=l.idx+ll;j++) str[j]='/'; for(int j=r.idx;j>=r.idx-ll;j--) str[j]='\\'; l=r; cnt=1; } else if(l.ty=='\\'&&r.ty=='\\') { for(int j=l.idx;j<=r.idx;j++) str[j]='\\'; l=r; cnt=1; } else if(l.ty=='\\'&&r.ty=='/') { l=r; cnt=1; } } } for(int i=0;i<len;i++) { if(str[i]=='/') break; else if(str[i]=='\\') { for(int j=0;j<=i;j++) { str[j]='\\'; } break; } } for(int i=len-1;i>=0;i--) { if(str[i]=='\\') break; else if(str[i]=='/') { for(int j=i;j<len;j++) { str[j]='/'; } break; } } for(int i=0;i<len;i++) printf("%c",str[i]); return 0; }
F. Distribution of wealth
It involves operation symbol overloading and priority queue
Define a structure first
struct point { int a,b,x; int power,ans; }
We use
bool operator <(const point that)const { return this->power<=that.power; }
To overload the operator "<" (the basic format is like this), so that the < operation of the structure can be meaningful. Then, define a priority queue to store the structure, and the structure will be sorted according to the less than sign
The basic idea is to give m yuan to everyone, but each time, according to the greedy idea, give it to the person who has the least increase in losses. Then, the priority queue is maintained by subtracting the amount of the person who has not been allocated a dollar from the amount of the person who has been allocated a dollar:
f(x+1)-f(x), which is the growth value of this person's loss after sharing a dollar
power=-a*(int)pow(x+1-b,2)+a*(int)pow(x-b,2);
Every time the first priority queue must have the least growth, then we take it out of the priority queue, add the money + 1, and put it back in the priority queue to ensure that the loss growth is the least after each dollar is distributed to one person
#include<iostream> #include<cmath> #include<queue> #define int long long using namespace std; struct point { int a,b,x; int power,ans; bool operator <(const point that)const { return this->power<=that.power; } void get_power() { power=-a*(int)pow(x+1-b,2)+a*(int)pow(x-b,2); } void get_ans() { ans=-a*(int)pow(x-b,2); } }arr[100005]; signed main() { int n,m,Ans=0; scanf("%lld%lld",&n,&m); for(int i=1;i<=n;i++) scanf("%lld",&arr[i].a); priority_queue<point>qu; for(int i=1;i<=n;i++) { scanf("%lld",&arr[i].b); arr[i].x=0; arr[i].get_power(); qu.push(arr[i]); } point temp; while(m--) { temp=qu.top(); qu.pop(); temp.x++; temp.get_power(); qu.push(temp); } while(qu.size()) { temp=qu.top(); qu.pop(); temp.get_ans(); Ans+=temp.ans; } printf("%lld",Ans); return 0; }
G. Score contempt
Slightly changed reverse order to the board questions For example:
4 1 3 3 5
Under normal circumstances, zzf senior students should get the following scores:
1 2 3 4
We try to subtract his due score from the current score to get:
0 1 0 1
You will find that the second and fourth times exceed his expectations, so they will not despise each other, because they are at the same level, but the second time will despise the first time, because the level of the second time is 1 grade higher than that of the first time That is, according to the second standard, the first score should be 2, but it is smaller than, which leads to a contempt This is the board of reverse order pair. Then I will set up the tree array board. I can try to learn the solution of reverse order pair
#include<iostream> using namespace std; int a[100005]; int vis[1000006]; int maxx=0; int lowbits(int x) { return x-(x&(x-1)); } int query(int x) { int res=0; while(x) { res+=vis[x]; x-=lowbits(x); } return res; } void add(int x) { while(x<=maxx) { vis[x]+=1; x+=lowbits(x); } } int main() { int n,ans=0; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); a[i]=a[i]-i+100000; maxx=max(a[i],maxx); } for(int i=1;i<=n;i++) { ans=(ans+query(a[i]-1))%12345; add(a[i]); } printf("%d",ans); return 0; }
H. The road to happiness
No tree dp, I can reopen it
Summary: this game is mainly simulation, involving a small number of algorithms and stl containers dp has no simple problem, and greed is difficult