测试题---共4题。时限1s,内存128M。
distinct
【问题描述】
陶陶为了给一道平面几何题出数据,需要产生 N 个点(x[i],y[i])。
已知x,y是由伪随机函数顺序产生,即:X[i+1] = (X[i]*Ax+Bx+i) mod Cx (X[1], Ax,Bx,Cx 是事先给定的)
Y[i+1] = (Y[i]*Ay+By+i) mod Cy (Y[1], Ay,By,Cy 是事先给定的)这样,就可以快速连续产生很多点坐标(X[i], Y[i])。不幸的是,这样产生的点有可能有相同的,虽然这种几率很少,但严谨的陶陶不允许这种事发生。
陶陶要求你帮助他解决最少要产生前多少项时,正好有 N 个不相同的点。输入格式:第一行。一个整数 N .第二行:4个整数 X[1]、 Ax、Bx、Cx .第三行:4个整数 Y[1]、 Ay、By、Cy .输出格式:一个整数 M 。表示最少要连续产生 M 个点,正好有 N 个不相同的点。数据保证有答案。
数据范围:1<=N<=1,000,000, 其它所有数据都在[1...1,000,000,000]范围内。
输入样例(distinct.in):
21
2 4 3 6
5 2 3 13
输出样例(distinct.out):
24
//我打了四段代码可是只有一段AC~~~其他三段都是50分30分TLE,也许这道题就是针对这个出的吧。
1 //#include<cstdio>
2 #include<fstream>
3 using namespace std;
4 ifstream cin("distinct.in");
5 ofstream cout("distinct.out");
6 long long n;
7 long long hash[4000038];
8 long long xx[4000038],yy[4000038];
9 long long x,ax,bx,cx;
10 long long y,ay,by,cy;
11 long long tot;
12 int main()
13 {
14 cin>>n;
15 cin>>x>>ax>>bx>>cx;
16 cin>>y>>ay>>by>>cy;
17 long long sum=1,i=1;
18 while (sum<n)
19 {
20 i++;
21 x=(x*ax+bx+i-1)%cx;
22 y=(y*ay+by+i-1)%cy;
23 long long t=(x*1321+y*1417)%4000037;
24 while (hash[t]!=0&&(xx[hash[t]]!=x||yy[hash[t]]!=y)) t=(t+9973)%4000037;
25 if (hash[t])
26 {
27 if (xx[t]==x&&yy[t]==y) continue;
28 }
29 else
30 {
31 tot++;
32 xx[tot]=x;
33 yy[tot]=y;
34 hash[t]=tot;
35 sum++;
36 }
37 }
38 cout<<i<<endl;;
39 return 0;
40 }
41
1 #include<fstream>
2 #include<cstdlib>
3 #include<cstring>
4 #define maxn 3000010
5 using namespace std;
6 ifstream cin("distinct.in");
7 ofstream cout("distinct.out");
8 int n,tot,sum;
9 struct node
10 {
11 long long x,y,l,r;
12 }f[maxn];
13 int ax,bx,cx;
14 int ay,by,cy;
15 int main()
16 {
17 cin>>n;
18 cin>>f[1].x>>ax>>bx>>cx;
19 cin>>f[1].y>>ay>>by>>cy;
20 int i=1;
21 sum=1;
22 while (sum<n)
23 {
24 i++;
25 f[i].x=(f[i-1].x*ax+bx+i-1)%cx;
26 f[i].y=(f[i-1].y*ay+by+i-1)%cy;
27 int s=1;
28 while (1)
29 {
30 if (f[i].x<f[s].x)
31 {
32 if (!f[s].l) {f[s].l=i;sum++;break;}
33 else {s=f[s].l;continue;}
34 }
35 if (f[i].x>f[s].x)
36 {
37 if (!f[s].r) {f[s].r=i;sum++;break;}
38 else {s=f[s].r;continue;}
39 }
40 if (f[i].x==f[s].x)
41 {
42 if (f[i].y<f[s].y)
43 {
44 if (!f[s].l) {f[s].l=i;sum++;break;}
45 else {s=f[s].l;continue;}
46 }
47 if (f[i].y>f[s].y)
48 {
49 if (!f[s].r) {f[s].r=i;sum++;break;}
50 else {s=f[s].r;continue;}
51 }
52 if (f[i].y==f[s].y) break;
53 }
54
55 }
56 }
57 cout<<i<<endl;
58 return 0;
59 }
60
1 #include<fstream>
2 #include<cstdio>
3 #include<cstdlib>
4 #include<cstring>
5 #define maxn 1000010
6 using namespace std;
7 ifstream cin("distinct.in");
8 ofstream cout("distinct.out");
9 long long n,tot,sum;
10 long long x,y;
11 long long ax,bx,cx;
12 long long ay,by,cy;
13 struct node
14 {
15 long long x,y;
16 node *next;
17 }*a[16777216];
18 bool hash(int x,int y)
19 {
20 long long tmpx=x,tmpy=y,k=0,h=0,r=0;
21 while (tmpx)
22 {
23 h=((h<<6)+((tmpx ^ y) & 255))&16777215;
24 tmpx=tmpx>>5;
25 }
26 while (tmpy)
27 {
28 r=((r<<6)+((tmpy ^ x) & 255))&16777215;
29 tmpy=tmpy>>5;
30 }
31 h=(h+r)&16777215;
32 node *t=a[h];
33 while (t!=NULL)
34 {
35 if (t->x==x&&t->y==y) return false;
36 t=t->next;
37 }
38 // t=malloc(sizeof(node));
39 t=new(node);
40 t->x=x;
41 t->y=y;
42 t->next=a[h];
43 a[h]=t;
44 return true;
45 }
46
47 int main()
48 {
49 // freopen("distinct.in","r",stdin);
50 // freopen("distinct.out","w",stdout);
51 // scanf("%d\n",&n);
52 // scanf("%d%d%d%d\n",&x,&ax,&bx,&cx);
53 // scanf("%d%d%d%d\n",&y,&ay,&by,&cy);
54 cin>>n;
55 cin>>x>>ax>>bx>>cx;
56 cin>>y>>ay>>by>>cy;
57 long long i=1;
58 sum=1;
59 hash(x,y);
60 while (sum<n)
61 {
62 i++;
63 x=(x*ax+bx+i-1)%cx;
64 y=(y*ay+by+i-1)%cy;
65 if (hash(x,y)) sum++;
66 }
67 // printf("%d\n",i);
68 cout<<i<<endl;
69 return 0;
70 }
71
1 #include<fstream>
2 #include<cstdlib>
3 #include<cstring>
4 #define maxn 2000010
5 using namespace std;
6 ifstream cin("distinct.in");
7 ofstream cout("distinct.out");
8 int n,tot=0,sum=0;
9 struct node
10 {
11 long long x,y;
12 int pri;
13 node* ch[2];
14 }*root,tree[maxn];
15 long long x,ax,bx,cx;
16 long long y,ay,by,cy;
17 node *New_node(int x,int y)
18 {
19 node *p=&tree[++tot];
20 p->x=x;
21 p->y=y;
22 p->pri=rand()*rand();
23 p->ch[0]=p->ch[1]=NULL;
24 return p;
25 }
26 void rotate(node* &x,int t)
27 {
28 node *y=x->ch[t];
29 x->ch[t]=y->ch[!t];
30 y->ch[!t]=x;
31 x=y;
32 }
33 void insert(node* &now,node* new_node,int &sum)
34 {
35 if (now==NULL)
36 {
37 sum++;
38 now=new_node;
39 return;
40 }
41 int t;
42 if (now->x!=new_node->x)
43 {
44 t=now->x<new_node->x;
45 }
46 else
47 {
48 if (now->y!=new_node->y) t=now->y<new_node->y;
49 else
50 if (now->y==new_node->y) return;
51 }
52 insert(now->ch[t],new_node,sum);
53 if (now->ch[t]->pri>now->pri) rotate(now,t);
54 }
55 int main()
56 {
57 srand(time(NULL));
58 cin>>n;
59 cin>>x>>ax>>bx>>cx;
60 cin>>y>>ay>>by>>cy;
61 int i=1,sum=1;
62 root=New_node(x,y);
63 while (sum<n)
64 {
65 i++;
66 x=(x*ax+bx+i-1)%cx;
67 y=(y*ay+by+i-1)%cy;
68 insert(root,New_node(x,y),sum);
69 }
70 cout<<i<<endl;
71 return 0;
72 }
73
Allbarns
农民约翰打算建一个新的矩形谷仓。但是,矩形谷仓的4个角落不能在落在软土路基上,只能落在一些固定点上。
现在,他已经找到地面上有N(4 <= N <= 1,000)个点,角落只可以落在这些点上。
他想知道依次每加多一个点,可以建立新谷仓的方法数量,请你帮助他找到答案。
输入格式:
第1行:一个整数,N第2行至N +1行:每行有两个被空格分隔的整数的x,y,作为一个点的坐标。所有的x,y都不会超过16,000。所有点都是不同的。输出格式:共 N 行:每行表示当前可以建立的新的谷仓的数目。
样例输入(allbarns.in):
8
1 2
1 -2
2 1
2 -1
-1 2
-1 -2
-2 1
-2 -1
样例输出(allbarns.out):
0
0
0
0
0
1
3
6
样例解释:最后的答案是(1,2,6,5),(1,3,6,8),(1,4,6,7),(2,3,5,8),(2,4,5,7),(3,4,8,7)
#include<cstdio> int n,ans; int ax[1010],ay[1010]; int xx[1000010],yy[1000010],len[1000010],num[1000010]; int hash[4000040]; int count; int main() { freopen("allbarns.in","r",stdin); freopen("allbarns.out","w",stdout); scanf("%d\n",&n); for (int i=1;i<=n;i++) { scanf("%d%d\n",&ax[i],&ay[i]); for (int j=1;j<=i;j++) { int x=ax[i]+ax[j]; int y=ay[i]+ay[j]; int l=(ax[i]-ax[j])*(ax[i]-ax[j])+(ay[i]-ay[j])*(ay[i]-ay[j]); int p=(x*1321+y*1171+l*1091)%4000037; while (hash[p]&&(len[hash[p]]!=l||xx[hash[p]]!=x||yy[hash[p]]!=y)) p=(p+9973)%4000037; if (!hash[p]) { count++; xx[count]=x; yy[count]=y; len[count]=l; num[count]=1; hash[p]=count; } else{ans+=num[hash[p]];num[hash[p]]++;} } printf("%d\n",ans); } return 0; }
cubes
FJ和Best用 N (1 <= N <= 30,000)块相同的小立方块玩游戏,小方块编号为1..N。开始时,小方块都单独分开的,每个看成一个柱子,即有 N 柱子。
FJ要Best做 P(1 <= P <= 100,000) 个操作,操作有两种类型:(1) FJ要求Best把X号方块所在的柱子放到Y号所在的柱子上面,成一个新柱子。
(2)FJ要求Best计算X号方块所在柱子,它下面有多少个小方块。
请编个程序,帮助Bet计算。输入格式:*第一行:一个整数 P*第2..P+1行:第i+1行表示第i个FJ要求的合法操作。
如果这行以'M'开头,后面有两个整数 X,y 表示要进入(1)操作。 如果这行以'C'开头,后面有一个整数 X,表示要求计算X所在柱子下面的方块个数。
注:所有操作都是合法的。N 并没有出现在输入文件中。输出格式:依次要求计算的值,每次一行。
输入样例 (cubes.in):
6 | 6个操作
M 1 6 | 1,6 / 2 / 3 / 4 / 5 把1放在6上面。
C 1 | 输出:1
M 2 4 | 1,6 / 2,4 / 3 / 5
M 2 6 | 2,4,1,6 / 3 / 5
C 3 | 输出 :0
C 4 | 输出: 2
输出样例(cubes.out)
1
0
2
#include<cstdio> #include<cstdlib> #define maxn 30010 int p; int father[maxn]; int before[maxn]; int tot[maxn]; char c; int get(int x) { if (father[x]==x) return x; int t=get(father[x]); before[x]+=before[father[x]]; father[x]=t; return father[x]; } void make(int x,int y) { int a=get(x); int b=get(y); if (a!=b) { father[a]=b; before[a]+=tot[b]; tot[b]+=tot[a]; } } int main() { freopen("cubes.in","r",stdin); freopen("cubes.out","w",stdout); scanf("%d\n",&p); for (int i=1;i<maxn;i++) { father[i]=i; tot[i]=1; } int x,y; for (int i=1;i<=p;i++) { scanf("%c",&c); if (c=='M') { scanf("%d%d\n",&x,&y); make(x,y); continue; } if (c=='C') { scanf("%d\n",&x); get(x); printf("%d\n",before[x]); } } }
friend
【问题描述】
有一个镇有N个居民。当然其中有许多人是朋友的关系。根据有名的谚语:“我朋友的朋友也是我的朋友”,所以如果A和B是朋友,B和C是朋友,
那么A和C也是朋友。你的任务是算出在这个镇中最大的朋友集团为多少人。
【输入文件】
输入文件的第一行有2个正整数 N 和 M 。N代表镇上居民的数目(1 <= N <= 30000 ),
M 代表这些居民中朋友关系的数目( 0 <= M <= 30000)。接下来的M行每行有2个整数A,B( 1 <= A,B <= N , A不等于B),
代表A,B为朋友关系。这M行中可能有的会重复出现。
【输出文件】输出文件仅一行,在这个镇中最大的朋友集团为多少人。
【输入样例】
10 12
1 2
3 1
3 4
5 4
3 5
4 6
5 2
2 1
7 10
1 2
9 10
8 9
【输出样例】
6
#include<cstdio> #include<cstring> #include<cstdlib> int n,m; int father[30010]; int sum[30010]; int ans; int get(int x) { if (father[x]==x) return x; father[x]=get(father[x]); return father[x]; } void make(int x,int y) { int a=get(x); int b=get(y); if (a!=b) father[a]=b; } int main() { freopen("friend.in","r",stdin); freopen("friend.out","w",stdout); scanf("%d%d\n",&n,&m); for (int i=1;i<=n;i++) father[i]=i; int a,b; for (int i=1;i<=m;i++) { scanf("%d%d\n",&a,&b); make(a,b); } for (int i=1;i<=n;i++) { int t=get(i); sum[t]++; if (sum[t]>ans) ans=sum[t]; } printf("%d\n",ans); return 0; }