14年安徽省赛数论题etc.

 关于最大公约数的疑惑

 

题目描述

 小光是个十分喜欢素数的人,有一天他在学习最大公约数的时候突然想到了一个问题,他想知道从1nn个整数中有多少对最大公约数为素数的(x,y),即有多少(x,y),gcd(x,y)=素数,1<=x,y<=n。但是小光刚刚接触最大公约数,不能解决这个问题,于是他希望你能帮助他解决这个问题。

输入

 多组测试数据,对于每组数据:

每行为一个整数N  (1<=N<=10^5)

输出

 对于每组数据:

每行输出 (x,y)的个数

样例输入

5

样例输出

5

直接筛法求素数+欧拉函数。在筛法求素数的时候顺便给每个数*(1-1/pi)其中pi为该数的质因子。
然后嘛 这题有点坑  他说的数对竟然是包括相同两个数的数对 以及例如(2,4)及(4,2)这样顺序不同的数对算作两个数对。。。所以我刚打的时候好几遍都不能AC...
贴代码:
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #define clr(x) memset(x,0,sizeof(x))
 5 using namespace std;
 6 
 7 int a[100001];
 8 int ct[100001];
 9 int pr[100001];
10 void prime(int n);
11 int main()
12 {
13     int n,m,i,j,sum;
14     prime(100000);
15     while(scanf("%d",&n)==1)
16     {
17         sum=0;
18         for(i=1;pr[i]<=n;i++)
19         {
20             j=n/pr[i];
21             sum+=ct[j]; 
22         }
23         printf("%d\n",sum*2+i-1);
24     }
25     
26  } 
27 void prime(int n)
28 {
29     clr(a);
30     clr(pr);
31     int num=0;
32      a[0]=a[1]=1;
33      for(int i=1;i<=n;i++)
34        ct[i]=i;
35     ct[1]=0;
36      for(int i=1;i<=n;i++)
37      if(!a[i])
38      {
39          for(int j=i;j<=n;j+=i)
40          {
41              a[j]=1;
42              ct[j]=ct[j]/i*(i-1);
43          }
44          pr[++num]=i;
45      }
46     for(int i=1;i<=n;i++)
47       ct[i]+=ct[i-1];
48     pr[0]=num;
49     return ;
50 }

一道简单的几何变换

题目描述

 小光最近在学习几何变换,老师给他留了一个作业,在二维平面上有n个点(x,y),老师给了m个几何变换对n个点进行操作,要求小光输出变换后的n个点的坐标(x’,y’)。小光为了偷懒,请求你帮他写个程序来完成老师的作业。

   由于小光刚刚学习几何变换,老师只会给出四种变换,如下:

   平移变换: (x’,y’)=(x+p,y’+q)   程序的输入格式为:1 p q  (p,q为整数

   缩放变换: (x’,y’)=(x*L,y*L)    程序的输入格式为:2 L    (L为整数)

   上下翻转: (x’,y’)=(x,-y)       程序的输入格式为:3

   左右翻转: (x’,y’)=(-x,y)       程序的输入格式为:4

 

输入

 多组测试数据,对于每组数据:

第一行为N(1<=N<=10^5)

   然后以下N行,N个点(x,y)  其中x,y均为整数

   然后一行为M  (1<=M<=10^5)

   然后以下M行,M个变换,输入格式如上所述。

输出

 对于每组数据:

输出N行,每行为变换点坐标。

样例输入

2 1 1 2 2 1 1 1 1

样例输出

2 2 3 3

这题也没什么好说的。。其实算不上数论,只是顶着变换的名头= =。然后呢一看数据量如果分别一个一个处理一定会超时。于是就想到了把所有的处理化为一次处理。
然后呢 用ct 代表全部处理过后是否翻转变换 =1为没翻转,=-1为翻转了。两次翻转相当于没翻转。每次翻转后ct=-ct。
用l表示全部处理过后的缩放倍数。
然后平移变换和翻转以及缩放相关,处理比较麻烦,用acum存最后处理完平移的多少。每次平移变换为acum=+a*ct。每次缩放时acum=*t,t为每次缩放变换的大小
对于每个数a[i]处理完后为a[i].x=a[i].x*l*ctx+acumx*ctx;    a[i].y=a[i].y*l*cty+acumy*cty;
代码处理如下:

 1 #include<cstdio>
 2 #include<iostream>
 3 using namespace std;
 4 struct pos{
 5 int x,y;
 6 }a[100001];
 7 int main()
 8 {
 9 int ctx,cty,acumx,acumy;
10 int n,m,k,l,t,p,q;
11 while(scanf("%d",&n)==1)
12 {
13 for(int i=1;i<=n;i++)
14 scanf("%d%d",&a[i].x,&a[i].y);
15 scanf("%d",&m);
16 ctx=cty=l=1;
17 acumx=acumy=0;
18 for(int i=1;i<=m;i++)
19 {
20 scanf("%d",&k);
21 if(k==1)
22 {
23 scanf("%d%d",&p,&q);
24 acumx+=ctx*p;
25 acumy+=cty*q;
26 }
27 if(k==2)
28 {
29 scanf("%d",&t);
30 l*=t;
31 acumx*=t;
32 acumy*=t;
33 }
34 if(k==3)
35 cty=-cty;
36 if(k==4)
37 ctx=-ctx;
38 }
39 for(int i=1;i<=n;i++)
40 {
41 a[i].x=a[i].x*l*ctx+acumx*ctx;
42 a[i].y=a[i].y*l*cty+acumy*cty;
43 printf("%d %d\n",a[i].x,a[i].y);
44 }
45 }
46 return 0;
47 }
View Code

 

posted @ 2016-04-07 12:21  hk_lin  阅读(303)  评论(0编辑  收藏  举报