训练赛题解

突然想到好久以前做完这份题目没写题解。蛮来写写吧。很多细节已经忘记了。。

第一题

很简单的字符串比对是否b包含a。不包含就报NO,包含就YES。。坑爹的第一次!!。把strlen放在了for循环里面。。就超时了。。超时了。。

注意:for里面的条件每次也会重新计算。

A - All in All

Time Limit:1000MS     Memory Limit:30000KB     64bit IO Format:%I64d & %I64u

Submit Status Practice POJ 1936

Description

You have devised a new encryption technique which encodes a message by inserting between its characters randomly generated strings in a clever way. Because of pending patent issues we will not discuss in detail how the strings are generated and inserted into the original message. To validate your method, however, it is necessary to write a program that checks if the message is really encoded in the final string.

Given two strings s and t, you have to decide whether s
is a subsequence of t, i.e. if you can remove characters from t such
that the concatenation of the remaining characters is s.

Input

The input contains several testcases. Each is specified by two strings
s, t of alphanumeric ASCII characters separated by whitespace.The length
of s and t will no more than 100000.

Output

For each test case output "Yes", if s is a subsequence of t,otherwise output "No".

Sample Input

sequence subsequence
person compression
VERDI vivaVittorioEmanueleReDiItalia
caseDoesMatter CaseDoesMatter

Sample Output

Yes
No
Yes
No

下附代码
 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<string.h>
 4 #include<cmath>
 5 #define INF 1000000
 6 char s[100005],t[100005];
 7 int main()
 8 {
 9     int i=0,j=0,s_len,t_len;
10     while(scanf("%s%s",s,t)!=EOF)
11     {
12         i=0;j=0;
13         s_len=strlen(s);
14         t_len=strlen(t);
15         for(i;i<s_len&&j<t_len;)
16             if(s[i]==t[j])
17                 {i++;j++;}
18             else
19                 j++;
20         if(i==strlen(s))
21             printf("Yes\n");
22         else
23             printf("No\n");
24     }
25     return 0;
26 }

第二题

找规律。。其实也可以还原。但是找到规律的话也是可以做的。就是写代码的时候要认真点。思路是相邻做差,得到一个新的数组,新数组有数字,说明肯定有差括号,是1,然后这个新数组如果有一串0,说明原来的数字都是相等的,则第一位0肯定是1,但是接下来的0,就要继续往前找对应的括号,然后增加数字,具体的已经忘记了。但是就是找规律。这题1A。

B - Parencodings

Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I64u

Submit Status Practice POJ 1068

Description

Let S = s1 s2...s2n be a well-formed string of parentheses. S can be encoded in two different ways:
q By an integer sequence P = p1 p2...pn where pi is the
number of left parentheses before the ith right parenthesis in S
(P-sequence).

q By an integer sequence W = w1 w2...wn where for each right
parenthesis, say a in S, we associate an integer which is the number of
right parentheses counting from the matched left parenthesis of a up to
a. (W-sequence).

Following is an example of the above encodings:

 S		(((()()())))
 P-sequence	    4 5 6666  W-sequence	    1 1 1456 

Write a program to convert P-sequence of a well-formed string to the W-sequence of the same string.

Input

The first line of the input contains a single integer t (1 <= t <= 10), the number of test cases, followed by the input data for each test case. The first line of each test case is an integer n (1 <= n <= 20), and the second line is the P-sequence of a well-formed string. It contains n positive integers, separated with blanks, representing the P-sequence.

Output

The output file consists of exactly t lines corresponding to test cases. For each test case, the output line should contain n integers describing the W-sequence of the string corresponding to its given P-sequence.

Sample Input

2
6
4 5 6 6 6 6
9
4 6 6 6 6 8 9 9 9

Sample Output

1 1 1 4 5 6
1 1 2 4 5 1 1 3 9

下附代码:
 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<string.h>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<queue>
 7 #define INF 1000005
 8 using namespace std;
 9 queue<int>q;
10 int s[1000005]={0},mark[1000005];
11 int main()
12 {
13     int n,first,late,i,m,ans,t;
14     scanf("%d",&n);
15     while(n--)
16     {
17         for(i=0;i<30;i++)
18             {s[i]=0;mark[i]=0;}
19         scanf("%d",&m);
20         first=0;
21         for(i=0;i<m;i++)
22             {
23                 scanf("%d",&late);
24                 s[i]=late-first;
25                 first=late;
26             }
27         for(i=0;i<m;i++)
28         {
29             if(s[i])
30             {
31               if(i!=m-1)
32                     printf("1 ");
33                 else
34                     printf("1\n");
35             }
36             else
37             {
38                 t=i;ans=0;
39                 while(!s[t]||mark[t]==s[t])
40                 {
41                     ans+=mark[t];
42                     t--;
43                 }
44                 while(mark[t]+1==s[t])
45                 {
46                     mark[t]++;
47                     ans+=s[t];
48                     t--;
49                     while(!s[t]||mark[t]==s[t])
50                     {
51                         ans+=mark[t];
52                         t--;
53                     }
54                 }
55                 mark[t]++;
56                 if(i!=m-1)
57                     printf("%d ",ans+mark[t]+1);
58                 else
59                     printf("%d\n",ans+mark[t]+1);
60             }
61         }
62     }
63     return 0;
64 }

第三题

一个二叉树的前序中序序列,还原后序序列,用到了递归分治的思想,主要要分清楚两个序列的头和尾在哪里,然后可以通过找根找到中序序列中间的根,从而继续分开这两个序列。关键代码是下面这个

if(k-cc)
        turn(aa+1,k-cc+aa,cc,k-1);
if(dd-k)
        turn(aa+k-cc+1,bb,k+1,dd);

错了两次,算是一道考细节的递归。下附代码:
 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<string.h>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<queue>
 7 #define INF 1000000
 8 using namespace std;
 9 char a[50],b[50],c[50];
10 void turn(int aa,int bb,int cc,int dd)//n是前序m是中序
11 {
12     int k=0;
13     while(a[aa]!=b[k])
14     {
15         k++;
16     }//找根
17     if(k-cc)
18         turn(aa+1,k-cc+aa,cc,k-1);
19     if(dd-k)
20         turn(aa+k-cc+1,bb,k+1,dd);
21     printf("%c",a[aa]);
22 }
23 int main()
24 {
25     int i,m,n,ans,t,bg,j,num,k,h=0,sum=0;
26     while(scanf("%s%s",a,b)!=EOF)
27     {
28         t=strlen(a);
29         turn(0,t-1,0,t-1);
30         for(i=1;i<=t;i++)
31             printf("%c",c[i]);
32         printf("\n");
33     }
34     return 0;
35 }

第四题:

BFS就行。用队列来存,注意一下具体细节。

D - Catch That Cow

Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u

Submit Status Practice POJ 3278

Description

Farmer John has been informed of the location of a fugitive cow and wants to catch her immediately. He starts at a point N (0 ≤ N ≤ 100,000) on a number line and the cow is at a point K (0 ≤ K ≤ 100,000) on the same number line. Farmer John has two modes of transportation: walking and teleporting.

* Walking: FJ can move from any point X to the points X - 1 or X + 1 in a single minute
* Teleporting: FJ can move from any point X to the point 2 × X in a single minute.

If the cow, unaware of its pursuit, does not move at all, how long does it take for Farmer John to retrieve it?

Input

Line 1: Two space-separated integers:
N and K

Output

Line 1: The least amount of time, in minutes, it takes for Farmer John to catch the fugitive cow.

Sample Input

5 17

Sample Output

4

Hint

The fastest way for Farmer John to reach the fugitive cow is to move along the following path: 5-10-9-18-17, which takes 4 minutes.

下附代码:

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<string.h>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<queue>
 7 #define INF 1000000
 8 using namespace std;
 9 queue<int>q;
10 int vis[1000005]={0};
11 int main()
12 {
13     int a,b,cot,ans,t,mark=0,noww;
14     scanf("%d%d",&a,&b);
15     if(a==b)
16         printf("0\n");
17     else
18     {
19         if(a+1==b||a-1==b||a*2==b)
20             printf("1\n");
21         else
22         {
23             q.push(a);
24             vis[a]=1;
25             while(!q.empty())
26             {
27                 ans=q.front();
28                 q.pop();
29                 if(ans-1>=0)
30                     {
31                         noww=ans-1;
32                         if(!vis[noww])
33                         {vis[noww]=vis[ans]+1;q.push(noww);}
34                         if(noww==b)
35                             {printf("%d\n",vis[noww]-1);break;}
36                     }
37                 if(ans+1<INF)
38                 {
39                     noww=ans+1;
40                     if(!vis[noww])
41                         {vis[noww]=vis[ans]+1;q.push(noww);}
42                     if(noww==b)
43                             {printf("%d\n",vis[noww]-1);break;}
44                 }
45                 if(ans*2<INF)
46                 {
47                     noww=ans*2;
48                     if(!vis[noww])
49                         {vis[noww]=vis[ans]+1;q.push(noww);}
50                     if(noww==b)
51                         {printf("%d\n",vis[noww]-1);break;}
52                 }
53             }
54         }
55     }
56     return 0;
57 }

第五题:

一道判断是不是连通的,用并查集就可以判断,但是要做一点小处理,存储的时候如果就一个数字就不管他,如果有两个或两个以上就用第一个数字当父亲,让后面其他的数字与其关联。

E - The Suspects

Time Limit:1000MS     Memory Limit:20000KB     64bit IO Format:%I64d & %I64u

Submit Status Practice POJ 1611

Description

Severe acute respiratory syndrome (SARS), an atypical pneumonia of unknown aetiology, was recognized as a global threat in mid-March 2003. To minimize transmission to others, the best strategy is to separate the suspects from others.
In the Not-Spreading-Your-Sickness University (NSYSU), there
are many student groups. Students in the same group intercommunicate
with each other frequently, and a student may join several groups. To
prevent the possible transmissions of SARS, the NSYSU collects the
member lists of all student groups, and makes the following rule in
their standard operation procedure (SOP).

Once a member in a group is a suspect, all members in the group are suspects.

However, they find that it is not easy to identify all the
suspects when a student is recognized as a suspect. Your job is to write
a program which finds all the suspects.

Input

The input file contains several cases. Each test case begins with two
integers n and m in a line, where n is the number of students, and m is
the number of groups. You may assume that 0 < n <= 30000 and 0
<= m <= 500. Every student is numbered by a unique integer between
0 and n−1, and initially student 0 is recognized as a suspect in all
the cases. This line is followed by m member lists of the groups, one
line per group. Each line begins with an integer k by itself
representing the number of members in the group. Following the number of
members, there are k integers representing the students in this group.
All the integers in a line are separated by at least one space.

A case with n = 0 and m = 0 indicates the end of the input, and need not be processed.

Output

For each case, output the number of suspects in one line.

Sample Input

100 4
2 1 2
5 10 13 11 12 14
2 0 1
2 99 2
200 2
1 5
5 1 2 3 4 5
1 0
0 0

Sample Output

4
1
1下附代码:
 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<string.h>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<queue>
 7 #define INF 1000005
 8 using namespace std;
 9 int f[30005],mark[30005],mark1[30005]={0};
10 int finding(int x)
11 {
12     if(x!=f[x])
13         f[x]=finding(f[x]);
14     return f[x];
15 }
16 int together(int x,int y)
17 {
18     int f1=finding(x);
19     int f2=finding(y);
20     if(f1!=f2)
21         {f[f2]=f1;return 1;}
22     return 0;
23 }
24 int main()
25 {
26     int i,m,n,ans,t,bg,j,num,k,h=0,cot=0,sum,late,temp;
27     while(scanf("%d%d",&n,&m)&&(n!=0||m!=0))
28     {
29         for(i=0;i<=n;i++)
30             f[i]=i;
31         k=0;
32         while(m--)
33         {
34             scanf("%d",&num);
35             if(num>1)
36                 {
37                     scanf("%d",&bg);
38                     if(!mark1[bg])
39                     {mark[k++]=bg;mark1[bg]=1;}
40                     for(i=1;i<num;i++)
41                         {
42                             scanf("%d",&late);
43                             together(bg,late);
44                             if(!mark1[late])
45                             {mark[k++]=late;mark1[late]=1;}
46                         }
47                 }
48             else if(num==1)
49                 {scanf("%d",&temp);
50                 if(!mark1[temp])
51                 {mark[k++]=temp;mark1[temp]=1;}}
52         }
53         sum=0;
54         for(i=0;i<k;i++)
55         {
56             if(finding(0)==finding(mark[i]))
57                 sum++;
58         }
59         if(sum==0)
60             printf("1\n");
61         else
62             printf("%d\n",sum);
63         for(i=0;i<k;i++)
64             mark1[mark[i]]=0;
65     }
66     return 0;
67 }

第六题:

一道超级水的最小生成树,用kruskal就可以。但是注意储存,只需要上三角就行。之前不小心数组开小了。就超了。。

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<string.h>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<queue>
 7 #define INF 1000000
 8 using namespace std;
 9 int f[100005];
10 struct node
11 {
12     int x;
13     int y;
14     int k;
15 }c[100005];
16 int cmp(struct node a,struct node b)
17 {
18     return a.k<b.k;
19 }
20 int finding(int x)
21 {
22     if(f[x]!=x)
23         f[x]=finding(f[x]);
24     return f[x];
25 }
26 int together(int x,int y)
27 {
28     int f1,f2;
29     f1=finding(x);
30     f2=finding(y);
31     if(f1!=f2)
32         {f[f2]=f1;return 1;}
33     return 0;
34 }
35 int main()
36 {
37     int i,m,n,ans,t,a,b,bg,j,num,k,h=0,sum=0;
38     while(scanf("%d",&n)!=EOF)
39     {
40         h=0;ans=0;sum=0;
41         for(i=0;i<100005;i++)
42             f[i]=i;
43         for(i=1;i<=n;i++)
44             for(j=1;j<=n;j++)
45                 {
46                     scanf("%d",&c[h].k);
47                     if(c[h].k!=0)
48                     {
49                         c[h].x=i;c[h].y=j;
50                         h++;
51                     }
52                 }
53         sort(c,c+h,cmp);
54         for(i=1;i<h;i++)
55         {
56             ans=together(c[i].x,c[i].y);
57             if(ans==1)
58             {
59                 sum+=c[i].k;
60             }
61         }
62         printf("%d\n",sum);
63     }
64     return 0;
65 }

第七题:

这题是最短路径,用dijkstra会超的原因居然是模板错了!!。最后只能用floyd反而过了。。无语。。模板害死人啊。

            if(s[j]==false&&dis[j]<mining)
            {
                u=j;mining=mapp[v][j];
            }这句才是真的

G - Tram

Time Limit:1000MS     Memory Limit:30000KB     64bit IO Format:%I64d & %I64u

Submit Status Practice POJ 1847

Description

Tram network in Zagreb consists of a number of intersections and rails connecting some of them. In every intersection there is a switch pointing to the one of the rails going out of the intersection. When the tram enters the intersection it can leave only in the direction the switch is pointing. If the driver wants to go some other way, he/she has to manually change the switch.

When a driver has do drive from intersection A to the
intersection B he/she tries to choose the route that will minimize the
number of times he/she will have to change the switches manually.

Write a program that will calculate the minimal number of
switch changes necessary to travel from intersection A to intersection
B.

Input

The first line of the input contains integers N, A and B, separated by a
single blank character, 2 <= N <= 100, 1 <= A, B <= N, N is
the number of intersections in the network, and intersections are
numbered from 1 to N.

Each of the following N lines contain a sequence of
integers separated by a single blank character. First number in the i-th
line, Ki (0 <= Ki <= N-1), represents the number of rails going
out of the i-th intersection. Next Ki numbers represents the
intersections directly connected to the i-th intersection.Switch in the
i-th intersection is initially pointing in the direction of the first
intersection listed.

Output

The first and only line of the output should contain the target minimal
number. If there is no route from A to B the line should contain the
integer "-1".

Sample Input

3 2 1
2 2 3
2 3 1
2 1 2

Sample Output

0下附代码:
 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<string.h>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<queue>
 7 #define INF 1000000
 8 using namespace std;
 9 int mapp[105][105],dis[105];
10 bool s[105];
11 int n;
12 void dijkstra(int v)
13 {
14     int i,j;
15     for(i=1;i<=n;i++)
16     {
17         dis[i]=mapp[v][i];
18         s[i]=false;
19     }
20     s[v]=true;
21     dis[v]=0;
22     for(i=2;i<=n;i++)
23     {
24         int mining=INF,u=v;
25         for(j=1;j<=n;j++)
26         {
27             if(s[j]==false&&dis[j]<mining)
28             {
29                 u=j;mining=mapp[v][j];
30             }
31         }
32         s[u]=true;
33         for(j=1;j<=n;j++)
34         {
35             if(s[j]==false&&mapp[u][j]<INF)
36                 if(mapp[u][j]+dis[u]<dis[j])
37                     dis[j]=mapp[u][j]+dis[u];
38         }
39     }
40 }
41 int main()
42 {
43     int i,m,ans,t,a,b,bg,j,num,k;
44     while(scanf("%d%d%d",&n,&a,&b)!=EOF)
45     {for(i=0;i<105;i++)
46         for(j=0;j<105;j++)
47             mapp[i][j]=INF;
48     for(i=1;i<=n;i++)
49     {
50         scanf("%d",&num);
51         for(j=0;j<num;j++)
52             {
53                 scanf("%d",&bg);
54                 if(j==0)
55                     mapp[i][bg]=0;
56                 else
57                     mapp[i][bg]=1;
58             }
59     }
60     /*for(i=1;i<=n;i++)
61         {for(j=1;j<=n;j++)
62             printf("%d ",mapp[i][j]);
63         cout<<endl;}*/
64     dijkstra(a);
65     /*for(j=1;j<=n;j++)
66         for(i=1;i<=n;i++)
67             for(k=1;k<=n;k++)
68                 if(mapp[i][j]+mapp[j][k]<mapp[i][k])
69                     mapp[i][k]=mapp[i][j]+mapp[j][k];*/
70     /*for(i=1;i<=n;i++)
71         printf("%d ",dis[i]);
72     cout<<endl;*/
73     if(dis[b]==INF)
74         printf("-1\n");
75     else
76         printf("%d\n",dis[b]);
77     /*if(mapp[a][b]==INF)
78         printf("-1\n");
79     else
80         printf("%d\n",mapp[a][b]);*/
81     }
82     return 0;
83 }

第八题:

这题以前做过,就是简单的素数筛一下,从小到大选择就好,注意。没有偶数。。我还调了半天。

J - Goldbach‘s Conjecture

Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u

Submit Status Practice POJ 2262

Description

In 1742, Christian Goldbach, a German amateur mathematician, sent a letter to Leonhard Euler in which he made the following conjecture:

Every even number greater than 4 can be
written as the sum of two odd prime numbers.

For example:

8 = 3 + 5. Both 3 and 5 are odd prime numbers.

20 = 3 + 17 = 7 + 13.

42 = 5 + 37 = 11 + 31 = 13 + 29 = 19 + 23.

Today it is still unproven whether the
conjecture is right. (Oh wait, I have the proof of course, but it is too
long to write it on the margin of this page.)

Anyway, your task is now to verify Goldbach‘s conjecture for all even numbers less than a million.

Input

The input will contain one or more test cases.

Each test case consists of one even integer n with 6 <= n < 1000000.

Input will be terminated by a value of 0 for n.

Output

For each test case, print one line of the form n = a + b, where a and b
are odd primes. Numbers and operators should be separated by exactly
one blank like in the sample output below. If there is more than one
pair of odd primes adding up to n, choose the pair where the difference b
- a is maximized. If there is no such pair, print a line saying
"Goldbach‘s conjecture is wrong."

Sample Input

8
20
42
0

Sample Output

8 = 3 + 5
20 = 3 + 17
42 = 5 + 37下附代码:
 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<string.h>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<queue>
 7 #define INF 1000005
 8 using namespace std;
 9 queue<int>q;
10 int s[1000005]={0},primee[1000005];
11 void prime()
12 {
13     int i,k=1,cot;
14     for(i=2;i<INF;i++)
15     {
16         if(s[i]==0)
17             primee[k++]=i;
18         cot=2;
19         while(cot*i<INF)
20         {
21             s[i*cot]=1;
22             cot++;
23         }
24     }
25 }
26 int main()
27 {
28
29     int i=1,n;
30     prime();
31     //for(i=1;i<100;i++)
32         //cout<<primee[i]<<" ";
33     while(scanf("%d",&n)&&n!=0)
34     {
35         i=1;
36         while(s[n-primee[i]])
37         {
38             i++;
39         }
40         printf("%d = %d + %d\n",n,primee[i],n-primee[i]);
41     }
42     return 0;
43 }

第九题:

简单的进位。字符串转成数字进行加减就好。

K - Primary Arithmetic

Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u

Submit Status Practice POJ 2562

Description

Children are taught to add multi-digit numbers from right-to-left one digit at a time. Many find the "carry" operation - in which a 1 is carried from one digit position to be added to the next - to be a significant challenge. Your job is to count the number of carry operations for each of a set of addition problems so that educators may assess their difficulty.

Input

Each line of input contains two unsigned integers less than 10 digits. The last line of input contains 0 0.

Output

For each line of input except the last you should compute and print the number of carry operations that would result from adding the two numbers, in the format shown below.

Sample Input

123 456
555 555
123 594
0 0

Sample Output

No carry operation.
3 carry operations.
1 carry operation.
下附代码:
 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<string.h>
 4 #include<cmath>
 5 char a[200005],b[200005];
 6 int main()
 7 {
 8     int carry,ans,t,s;
 9     while(scanf("%s%s",a,b)&&(a[0]!=‘0‘||b[0]!=‘0‘))
10     {
11         carry=0;
12         t=strlen(a)-1;s=strlen(b)-1;ans=0;
13         while(t>=0&&s>=0)
14         {
15             if((a[t]-48)+(b[s]-48)+carry>9)
16                 {
17                     carry=(a[t]-48)+(b[s]-48)+carry;
18                     ans++;
19                     carry/=10;
20                 }
21             t--;s--;
22         }
23         if(t<0)
24         {
25             while(s>=0)
26             {
27                  if((b[s]-48)+carry>9)
28                 {
29                     carry=(b[s]-48)+carry;
30                     ans++;carry/=10;s--;
31                 }
32                 else
33                     break;
34             }
35         }
36         if(s<0)
37         {
38             while(t>=0)
39             {
40                 if((a[t]-48)+carry>9)
41                 {
42                     carry=(a[t]-48)+carry;
43                     ans++;carry/=10;t--;
44                 }
45                 else
46                     break;
47             }
48         }
49         if(ans==0)
50             printf("No carry operation.\n");
51         else if(ans==1)
52             printf("1 carry operation.\n");
53         else
54             printf("%d carry operations.\n",ans);
55     }
56     return 0;
57 }
第十题:就是在n的范围内,互质的分数的个数。其实就是欧拉函数在1-n范围内求和,打个线性欧拉函数筛就搞定了。

L - Farey Sequence

Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u

Submit Status Practice POJ 2478

Description

The Farey Sequence Fn for any integer n with n >= 2 is the set of irreducible rational numbers a/b with 0 < a < b <= n and gcd(a,b) = 1 arranged in increasing order. The first few are
F2 = {1/2}

F3 = {1/3, 1/2, 2/3}

F4 = {1/4, 1/3, 1/2, 2/3, 3/4}

F5 = {1/5, 1/4, 1/3, 2/5, 1/2, 3/5, 2/3, 3/4, 4/5}

You task is to calculate the number of terms in the Farey sequence Fn.

Input

There are several test cases. Each test case has only one line, which contains a positive integer n (2 <= n <= 10 6). There are no blank lines between cases. A line with a single 0 terminates the input.

Output

For each test case, you should output one line, which contains N(n) ---- the number of terms in the Farey sequence Fn.

Sample Input

2
3
4
5
0

Sample Output

1
3
5
9下附代码:
 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<string.h>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<queue>
 7 #define INF 1000005
 8 using namespace std;
 9 int target[INF],phi[INF];
10 bool pri[INF];
11 int main()
12 {
13     int i,m,n,ans,t,bg,j,num,k,h=0,cot=0;
14     long long int sum=0;
15     for(i=2;i<INF;i++)
16     {
17         if(pri[i]==false)
18         {
19             target[cot++]=i;
20             phi[i]=i-1;
21         }
22         for(j=0;j<cot&&i*target[j]<INF;j++)
23         {
24             pri[i*target[j]]=true;
25             if(i%target[j]==0)
26                 phi[i*target[j]]=phi[i]*target[j];
27             else
28                 phi[i*target[j]]=phi[i]*(target[j]-1);
29         }
30     }
31     while(scanf("%d",&n)&&n!=0)
32     {
33         sum=0;
34         for(i=2;i<=n;i++)
35             sum+=phi[i];
36         printf("%lld\n",sum);
37     }
38     return 0;
39 }

其实还有两题。但都是比较困难的题目了。。待以后有余力的话继续补充。

又结束了一次训练,感觉还是没什么长进,希望暑假能提高代码能力。。加油!


 
				
时间: 2024-08-24 18:24:18

训练赛题解的相关文章

周一训练赛题解

这次完全是水题大集合啊,希望大家A的开心: 前两个题是我找的,后两个是陶叔找的,另外因为我的偷懒,下面所有的代码都是陶叔亲自写的,十分感谢陶叔: 陶叔暑假为了大家的集训,牺牲了很多自己宝贵的时间,大家接下来要好好训练啊!!!! 废话少说,进入正题: Problem A      SPOJ QUEST5 签到题: 将所有的边按照右端点排个序,然后每次选择没有钉住的点,然后把这之后的所有与它相交的边全去掉: 代码: #include <cstdio> #include <cstring>

cumt训练赛题解

2017年4月3日 cumt2017春季--训练赛(1) A.HihoCoder 1339 (dp) 思路: 比较清晰呢,就是个dp吧.定义一下状态,dp[i][j]:前i个骰子,扔出点数和为j的方案数.然后不就很好写了嘛递推式,dp[i][j] = dp[i - 1][j - k](1<=k<=6). 好像题就做完了诶,可是窝wa了两发什么鬼.第一发爆int,第二发爆longlong,这里的trick就是方案数可能非常大,所以这题的应该把状态定义为dp[i][j]:前i个骰子,扔出点数和为j

第三周训练赛题解

这次题目加强了搜索的练习,还有一些小技巧和基本方法,加了一道基础DP居然没人A确实是意料之外,C题的裸DFS也是很迷.蓝桥杯以爆搜为主,近期会加强搜索训练,做好准备. A: 给定一个整数n,将1~n排列成环使两两之间互质. DFS搜索所有可能的排列,输出. B: 问能否在恰好的时间从S->D 题目运用到了奇偶剪枝的方法, 根据题目,doggie必须在第t秒到达门口.也就是需要走t-1步.设doggie开始的位置为(sx,sy),目标位置为(ex,ey).如果abs(ex-x)+abs(ey-y)

2018.12.2 中国石油大学第一次新生训练赛题解

整理人: 周翔 A题:李继朋 B题:李继朋 H题:魏斯博 原文地址:https://www.cnblogs.com/QLU-ACM/p/10057831.html

HDU 5371 (2015多校联合训练赛第七场1003)Hotaru&#39;s problem(manacher+二分/枚举)

HDU 5371 题意: 定义一个序列为N序列:这个序列按分作三部分,第一部分与第三部分相同,第一部分与第二部分对称. 现在给你一个长为n(n<10^5)的序列,求出该序列中N序列的最大长度. 思路: 来自官方题解:修正了一些题解错别字(误 先用求回文串的Manacher算法,求出以第i个点为中心的回文串长度,记录到数组p中 要满足题目所要求的内容,需要使得两个相邻的回文串,共享中间的一部分,也就是说,左边的回文串长度的一半,要大于等于共享部分的长度,右边回文串也是一样. 因为我们已经记录下来以

HDU 5371 (2015多校联合训练赛第七场1003)Hotaru&amp;#39;s problem(manacher+二分/枚举)

pid=5371">HDU 5371 题意: 定义一个序列为N序列:这个序列按分作三部分,第一部分与第三部分同样,第一部分与第二部分对称. 如今给你一个长为n(n<10^5)的序列,求出该序列中N序列的最大长度. 思路: 来自官方题解:修正了一些题解错别字(误 先用求回文串的Manacher算法.求出以第i个点为中心的回文串长度.记录到数组p中 要满足题目所要求的内容.须要使得两个相邻的回文串,共享中间的一部分,也就是说.左边的回文串长度的一半,要大于等于共享部分的长度,右边回文串也

EXAM个人训练赛四

EXAM个人训练赛四 已完成 [x] A [x] D [x] E [x] F [x] J [x] K [x] I* 未完成 [x] B [x] C [x] G [x] H 签到水题 A J F A:英文字母有2426个 J:注意long long D:Transit Tree Path 我直接套了单源最短路的一个模板,有人用的是DFS,模板第一次用,记得是无向图. 代码又臭又长: #include<bits/stdc++.h> using namespace std; const int ma

EXAM个人训练赛五

EXAM个人训练赛五 已完成 [x] A [x] E [ ] K* [x] M* 未完成 [ ] C [ ] F 放弃没人做出来的题 A 要用ll,然后注意正方形的情况,细心一点 E 有点动态规划的感觉,状态的转移,不难,要注意不要漏掉状态 K 正解是DFS 然后用贪心数据弱的话能过,先排圆心 M 树状数组,可以维护前面有多少数比这个数小,然后通过相减也可以得出后面有多少数比它小,后面要用到容斥的思想 12xx(xx比1 2大)可以通过组合数算出,即前面比它小的选一个,后面比它大的选两个,然后相

1780 - 2019年我能变强组队训练赛第十八场

题目描述 wls有一个钟表,当前钟表指向了某一个时间. 又有一些很重要的时刻,wls想要在钟表上复现这些时间(并不需要依次复现).我们可以顺时针转动秒针,也可以逆时针转动秒针,分针和时针都会随着秒针按规则转动,wls想知道秒针至少转动多少角度可以使每个时刻至少都会被访问一次. 注意,时钟上的一种时针分针秒针的组合,可以代表两个不同的时间. 输入 第一行一个整数n代表有多少个时刻要访问. 第二行三个整数h,m,s分别代表当前时刻的时分秒. 最后n行每一行三个整数hi,mi,si代表每个要访问的时刻