AC代码:
#include
#include
#define maxn 1000005
int data[maxn];
int main()
{
int Case,count=1,i,j,old=2;
data[1]=2;
for(i=3;i<=maxn;i++)
{
int temp = sqrt(i);
for(j=2;j<=temp;j++)
if(i%j==0) break;
if(j>temp)
{
for(j=old;j<= i-1;j++) data[j]=i;
old=i;
}
}
scanf("%d",&Case);
while(Case--)
{
int n;
long long ans=0;
scanf("%d",&n);
for(i=0;i
B - Prime Independence
C - Aladdin and the Flying Carpet
题意:给出一个矩形的面积a,一个整数b,要求矩形的短边x>=b。问你还有这种矩形有几种可能。
实际上就是求sqrt(a)的因子中大于等于b的个数。
思路:唯一分解定理求解。唯一分解定理—一个数n可以唯一分解成n=p0^c0*p1^c1*...*pi^ci(pi为素数)
这题很奇怪,我写的代码一直T,我找的网上的代码就可以过。我甚至照着他的代码改也是T,很迷。这里给出
两份代码。希望有大佬能指出我T的原因。
AC代码:
#include
#include
#include
#include
#define ll long long
using namespace std;
int const MAX = 1e6 + 10;
int p[MAX];
bool u[MAX];
int num, cnt;
ll a, b, tmp;
void get_prime()
{
memset(u, false, sizeof(u));
for(int i = 2; i <= sqrt(MAX); i++)
if(!u[i])
for(int j = i * i; j <= MAX; j += i)
u[j] = true;
for(int i = 2; i <= MAX; i++)
if(!u[i])
p[cnt ++] = i;
}
void cal()
{
for(int i = 0; i < cnt && p[i] <= sqrt(tmp); i++)
{
int cc = 0;
while(tmp % p[i] == 0)
{
cc ++;
tmp /= p[i];
}
num *= (cc + 1);
}
if(tmp > 1) //如果tmp不能被整分,说明还有一个素数是它的约数,此时cc=1
num *= 2;
}
int main()
{
int T;
scanf("%d", &T);
cnt = 0;
get_prime();
for(int ca = 1; ca <= T; ca++)
{
scanf("%lld %lld", &a, &b);
if(a < b * b)
printf("Case %d: 0\n", ca);
else
{
num = 1;
tmp = a;
cal();
num /= 2;
for(int i = 1; i < b; i++)
if(a % i == 0)
num --;
printf("Case %d: %d\n", ca, num);
}
}
}
我的代码:
#include
#include
#define maxn 1000010
bool prim[maxn];
int su[maxn],cnt;
long long a,b,temp,ans;
void inti()
{
int i,j;
prim[1]=1;
for(i=2;i<=maxn;i++)
{
if(prim[i]==0)
{
for(j=i+i;j<=maxn;j+=i) prim[j]=1;
}
}
for(i=2;i<=maxn;i++)
if(prim[i]==0) su[cnt++]=i;
}
void cal()
{
int i;
int sq=sqrt(temp);
for(i=0;i1) ans*=2;
}
int main()
{
inti();
int Case,count=0;
scanf("%d",&Case);
//freopen("f.txt","w",stdout);
for(count=1;count<=Case;count++)
{
int i;
scanf("%lld%lld",&a,&b);
if(a<=b*b) printf("Case %d: 0\n",count);
else
{
ans=1; temp=a;
cal();
ans>>=1;
for(i=1;i
D - Sigma Function
题意:其实看题目就很清楚题意了。就是给了一个公式f(x),输入一个整数n,要求你输出1到n中,f(n)是偶数的个数。
思路:只要公式中有一项为偶数,那么f(n)就是偶数。所以我们反过来求奇数的个数再做个减法求得偶数的个数会更
容易些。看公式就会发现这公式其实是k个等比数列和的积。则当pi==2时,这一项便是奇数。因为pi是素数,所以
若pi!=2,则pi肯定是奇数。所以当pi!=2&&ei为偶数时,这一项便是奇数。
所以f(n)为奇数的情况就只有三种
1.n=2^k
2.n=x^2(ei为偶数,所以指数都可以提出一个2,这样就变成某个数的平方)
3.n=2*x^2(因为2的指数可偶可奇,偶数的情况包括在第二种情况,而奇数我们则提出一个2,就变成一个平方数的两倍)
综上,我们就可以给出AC代码了
#include
#include
#define maxn 1000000
int main()
{
int Case,count=0;
scanf("%d",&Case);
while(Case--)
{
long long s,ans=0,sq;
scanf("%lld",&s);
int i;
sq=(long long)sqrt((double)s);
for(i=1;i<=sq;i++)
{
ans++;
if((long long)2*i*i<=s) ans++;
}
printf("Case %d: %lld\n",++count,s-ans);
}
return 0;
}
E - Leading and Trailing
题意:给出两个整数n和k,求n^k的前三位和后三位。
思路:后三位很容易得到,主要是前三位应该如何求出。求前三位就要知道点东西了。一个数a我们可以写成a=10^x,
其中x是一个浮点数。所以,若有10^x=n^k的话,则令y=(x的小数部分),前三位便是100*pow(10.0,y)。
这样我们便可以给出AC代码
#include
#include
#include
using namespace std;
#define ll long long
int main()
{
int Case,count=0;
scanf("%d",&Case);
// ofstream my;
// my.open("temp.txt");
while(Case--)
{
int n,k,i,first,last;
scanf("%d%d",&n,&k);
first=n; last=1;
int temp=n,fk=k;
while(fk)
{
if(fk%2) last=(last*temp)%1000;
temp=((temp%1000)*(temp%1000))%1000;
fk>>=1;
}
double a=k*log10((double)n)-(long long)(k*log10((double)n));
a=pow(10.0,a);
printf("Case %d: %d %03d\n",++count,(int)(a*100),last%1000);
}
//my.close();
return 0;
}
F - Goldbach`s Conjecture
题意:验证哥德巴赫猜想:n=a+b,其中n为大于2的偶数,a<=b,给出n问有几种方案
思路:这....打表加暴力= =
AC代码:
#include
#include
#define maxn 10000000
bool Isprim[maxn];
int su[670000];
int cnt; //664579
void inti()
{
int i,j;
int sq=sqrt(maxn);
Isprim[1]=1;
for(i=2;i<=sq;i++)
{
if(Isprim[i]==0)
{
for(j=i*2;j
G - Harmonic Number (II)
题意:额...这个应该不用说了...题目都直接上代码了- -
思路:假如给了整数n,那么我们先求SUM(n/i),其中1<=i<=sqrt(n),之后我们再求出(n/x)=b(b<=sqrt)的个数,
然后都加起来就好了。不过要注意一点:如果(n/sqrt(n))==sqrt(n)的话,我们就要减去一个sqrt(n)
AC代码:
#include
#include
long long solve(long long s)
{
long long ans=0;
int sq=sqrt((double)s),i;
for(i=1;i<=sq;i++) ans+=(s/i);
//printf("%d %d\n",ans,sq);
for(i=1;i<=sq;i++)
{
ans+=i*((s/i)-(s/(i+1)));
//printf("%d\n",ans);
}
if(sq==(s/sq)) ans-=sq;
return ans;
}
int main()
{
int Case,count=0;
scanf("%d",&Case);
while(Case--)
{
long long s;
scanf("%lld",&s);
printf("Case %d: %lld\n",++count,solve(s));
}
return 0;
}
H - Pairs Forming LCM
题意:直接看题目代码就理解了- -
思路:由唯一分解定理:n=p0^c0*p1^c1*...*pi^ci,a=p0^d0*p1^d1*...*pi^di,b=p0^e0*p1^e1*...*pi^ei
若a b的最小公倍数是n,则c0=max(d0,e0),c1=max(d1,e1)..ci=max(di,ei)
则(a,b)共有(2*c0+1)(2*c1+1)...(2*ci+1)(+1是因为有这种情况:di==ei==ci)
最后的结果要除以2,因为(a,b)和(b,a)是一样的
AC代码:
#include
#include
const int maxn = 1e7+5;
int su[maxn/10],cnt;
bool prime[maxn];
void inti()
{
for(int i=2;i1) data[cc++]=1;
for(int i=0;i
I - Harmonic Number
题意:给一个整数n,求式子1+1/2+1/3+...+1/n
思路:这题数据量有10^8,首先想到的是打表,可是开10^8的double数组肯定会MLE,所以我们每隔100才记录一次
AC代码:
#include
#define maxn 1000005
double data[maxn];
int main()
{
int i; double s=1.0;
for(i=2; i<=100000000 ;i++)
{
s+=(1.0/i);
if(i%100==0) data[i/100]=s;
}
int Case,count=0;
scanf("%d",&Case);
while(Case--)
{
int a,i;
scanf("%d",&a);
double ans=data[a/100];
for(i=(a/100)*100+1;i<=a;i++)
ans+=(1.0/i);
printf("Case %d: %.9lf\n",++count,ans);
}
return 0;
}
J - Mysterious Bacteria
题意:其实题目巴拉巴拉说什么细菌我也看得不是很懂,这时候我们就要看样例猜题意了。实际上很简单,就是给你一个数n,有a^b=n,让你求出最大的b(例如n=64,n=2^6=4^3,这时候就要输出6,因为6是这些幂中最大的)
思路:很自然的就想到唯一分解定理了,n=p0^e0*p1^e1*...*pi^e1,那么答案ans就是e0 e1...ei这些指数的GCD...不过这里有一个坑点,就是n可能小于0,这时候我们的指数就不能是偶数,所以如果n<0,那么我们得加一句while(ans%2==0)ans/=2;
AC代码:
#include
#include
const int maxn = (1<<16)+5;
bool prime[maxn];
int su[maxn],cnt=0;
void inti()
{
for(int i=2; i1) ans=1;
else
{
ans =he[0];
//printf("%d",ans);
for(int i=1;i
K - Large Division
题意:给你两个整数a和b,问你a是否能整除b
思路:这里注意一下,a的数据量非常大,是不可能直接用long long的...所以我很无耻的掏出了java- -另外,这里直接取abs(a),abs(b)就好了...
AC代码:
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Scanner;
public class Main{
public static void main(String[] args){
Scanner cin =new Scanner(System.in);
int n = cin.nextInt();
BigInteger ZERO = BigInteger.valueOf(0);
for(int i=1;i<=n;i++){
BigInteger a,b,c;
a=cin.nextBigInteger(); b=cin.nextBigInteger();
a=a.abs(); b=b.abs();
c=a.mod(b);
System.out.print("Case "+i+": ");
if(c.equals(ZERO)) System.out.println("divisible");
else System.out.println("not divisible");
}
}
}
另外,C做大数实在是太麻烦了...建议看看Java...对于大数,Java不说秒出也差不多了
L - Fantasy of a Summation
题意:自己看题目给的代码吧- -
思路:本蒟蒻用的是看样例猜公式法- -公式:ans = k*n^(k-1)*SUM(a[i]),运算的时候注意取模
AC代码:
#include
int main()
{
//freopen("f.txt","w",stdout);
int cases,count=0; scanf("%d",&cases);
while(cases--)
{
int n,k,MOD;
int ans = 0;
scanf("%d%d%d",&n,&k,&MOD);
for(int i=0;i
M - Help Hanzo
题意:题目描述只需要看最后一段就好,就是让你求出整数a到b之间素数的个数
思路:第一反应当然是筛素数啊...不过数据量太大,直接求肯定会T。所以我们分两种情况来求。首先我们先素数打表,当然肯定不会直接打2^31,我打到2*10^5。如果给的数a小于这个范围,那么直接遍历素数数组,如果大于这个范围,那么我们就用类似筛素数的方法来做。
AC代码:
#include
#define maxn 200005
int su[maxn],cnt;
bool prime[maxn];
void inti()
{
int i,j;
prime[1]=1;
for(i=2;i
看了代码,可能有人会问,会不会有种情况是有一个素数n>2*10^5,可是a<=k*n<=b,这种情况不是漏了?但事实上不会,因为注意到2*10^5是大于2^16的,所以在这之前这种情况就已经被筛掉了。
N - Trailing Zeroes (III)
题意:给出一个整数Q,问你是否存在一个整数N,使得N!后恰好有Q个0,存在输出N,不存在输出impossible
思路:其实写几个阶乘看看就知道了。就是看这个数有几个5。不过这里我们得需要二分去找这个数。
AC代码:
#include
int main()
{
int Case,count=0;
scanf("%d",&Case);
while(Case--)
{
int n; scanf("%d",&n);
int l=4*n,r=5*n,flag=0;
int mid;
while(l<=r)
{
int mid=(l+r)>>1;
int mc=0,temp=mid;
while(temp) mc+=temp/5,temp/=5;
if(mcn) r=mid-1;
else {flag=mid;break;}
}
printf("Case %d: ",++count);
if(flag) printf("%d\n",flag-flag%5);
else printf("impossible\n");
}
return 0;
}
O - GCD - Extreme (II)
P - Code Feat
Q - Emoogle Grid
R - 青蛙的约会
题意:中文的就不用说了。
思路:我们照着题目要求推一下就会发现这其实就是裸的扩欧。 (x+ans*m)=k1*L+a,(y+ans*n)=k2*L+a
->(x-y)=L(k1-k2)+ans*(n-m)。不过这里注意,扩欧里是没有负数的。
AC代码:
#include
#define ll long long
ll exGcd(ll a, ll b, ll &x, ll &y)
{
if(!b)
{
x=1;
y=0;
return a;
}
ll r=exGcd(b,a%b,x,y);
ll t=x;
x=y;
y=t-(a/b)*y;
return r;
}
int main()
{
ll x,y,m,n,L;
scanf("%lld%lld%lld%lld%lld",&x,&y,&m,&n,&L);
ll a,b,ans,un;
a = x-y; b = n-m;
if(b<0) a=-a,b=-b;
ll c=exGcd(L,b,un,ans);
if(a%c!=0) printf("Impossible\n");
else printf("%lld\n",(((a/c)*ans)%L+L)%L);
return 0;
}
S - C Looooops
T - Death to Binary?
U - Primes
题意:问整数n是不是素数,题目给了1,2不是素数
思路:筛呗!
AC代码:
#include
#include
#define maxn 16005
bool primes[maxn];
int main()
{
int i,j;
primes[1]=0;
primes[2]=0;
for(i=3; i<=maxn; i++)
{
int temp=sqrt((double)i);
for(j=2; j<=temp; j++)
if(i%j==0) break;
primes[i]=(j>temp);
}
int n,count=0;
while(scanf("%d",&n) && n>0)
{
printf("%d: ",++count);
if(primes[n]) printf("yes\n");
else printf("no\n");
}
return 0;
}
V - Maximum GCD
题意:给出多个整数,求这些整数之间的最大GCD。
思路:这题就输入烦了点,暴力就好
AC代码:
#include
int Gcd(int a, int b)
{
return a%b?Gcd(b,a%b):b;
}
int Max(int a, int b)
{
if(a>b) return a;
return b;
}
int main()
{
int Case;
scanf("%d",&Case);
while(getchar()!='\n');
while(Case--)
{
int data[1005]={0},count=0;
char c;
int flag=0;
while((c=getchar())!='\n')
{
if(c==' ') {flag=1;continue;}
if(flag) count++,flag=0;
data[count]=data[count]*10+(c-'0');
}
int i,j,MMax=0;
for(i=0;i
W - Prime Time
题意:给了一个函数f(n),输入两个整数a,b,求a,b之间的f(x),问素数的比例。例:a=0,b=39,f(0),f(1)...(f39)这40个数素数的比例。
思路:筛素数再打表
AC代码:
#include
#include
bool prime(int n)
{
n=n*n+n+41;
int sq=sqrt(n),i;
for(i=2;i<=sq;i++)
if(n%i==0) break;
return (i>sq);
}
int main()
{
//freopen("f.txt","w",stdout);
bool ans[10005];
int i;
for(i=0;i<10005;i++)
ans[i]=prime(i);
int a,b;
while(scanf("%d%d",&a,&b)!=EOF)
{
int count=0;
for(i=a;i<=b;i++)
count+=ans[i];
//printf("%d %d\n",count,(b-a+1));
printf("%.2lf\n",100*((double)count/(double)(b-a+1))+0.000001);
}
return 0;
}
X - The equation
题意:让你求ax+by+c=0的解,其中解应满足x1<=x<=x2,y1<=y<=y2
思路:看到这式子很自然的就会想到扩欧吧。扩欧可以求一组特解x0,y0。则通解x=x0+k*b/Gcd(a,b),y=y0-k*a/Gcd(a,b)。然后解不等式就好了。这里有三个点要注意:一是a,b,c中存在负数的情况,二是a,b,c中存在为0的情况,三是最后求解k的时候需要注意向上或向下取整。
AC代码:
#include
#include
#include
#include
#include
using namespace std;
long long exGcd(long long a,long long b,long long &x,long long &y)
{
if(!b){
x=1; y=0; return a;
}
long long r=exGcd(b,a%b,x,y);
long long t=x;
x=y;
y=t-(a/b)*y;
return r;
}
int main(){
long long a,b,c,x1,x2,y1,y2;
scanf("%lld%lld%lld",&a,&b,&c);
scanf("%lld%lld",&x1,&x2);
scanf("%lld%lld",&y1,&y2);
long long ans = 0; c= (-c);
if(c<0) c=(-c),a=(-a),b=(-b);
if(a<0) swap(x1,x2),x1=(-x1),x2=(-x2),a=(-a);
if(b<0) swap(y1,y2),y1=(-y1),y2=(-y2),b=(-b);
if(!a||!b)
{
if(!a&&!b){
if(!c) printf("%lld\n",(x2-x1+1)*(y2-y1+1));
else printf("0\n");
}
else if(a==0){
long long temp=c/b;
if(c%b==0&&temp>=y1&&temp<=y2) printf("%lld\n",(x2-x1+1));
else printf("0\n");
}
else if(b==0){
long long temp=c/a;
if(c%a==0&&temp>=x1&&temp<=x2) printf("%lld\n",(y2-y1+1));
else printf("0\n");
}
return 0;
}
long long hx,hy; long long myGcd;
myGcd = exGcd(a,b,hx,hy);
if(c%myGcd!=0) printf("0\n");
else
{
long long cheng = c/myGcd;
double x = b/myGcd;
double y = a/myGcd;
hx*=cheng; hy*=cheng;
long long r=min(floor((x2-hx)/x),floor((hy-y1)/y));
long long l=max(ceil ((x1-hx)/x),ceil ((hy-y2)/y));
if(r>=l) ans=r-l+1;
else ans=0;
printf("%lld\n",ans);
}
return 0;
}
Y - Farey Sequence
题意:给一个整数n,问x(2<=x<=n)与(1,2....x-1)互质的个数
思路:裸的欧拉函数
AC代码:
#include
#include
const int maxn = 1e6+10;
int ans[maxn];
void inti()
{
int i,j;
ans[1]=1;
for(i=2;i
Z - The Super Powers
题意:emmm....突然不知道该怎么表述,举个例子吧...输出一组数,64是这组数中的一员,因为64可表示为2^6或者4^3
思路:很显然,只要某一个数的指数可分解就可以输出了...则显然的指数最小为4,那么我们可以用一个循环遍历2到2^16就好了。这里我们用了set,因为set去重而且是排好序的...
AC代码:
#include
#include
#include
#include
using namespace std;
#define ll unsigned long long
#define Max 18446744073709551614
bool prime[70];
int Count,he[70],cnt;
set data;
void inti()
{
int i,j;
for(i=2;i<65;i++)
{
if(prime[i])
{he[cnt++]=i;continue;}
for(j=i+i;j<65;j+=i)
prime[j]=1;
}
}
int main()
{
//freopen("f.txt","w",stdout);
inti();
data.insert(1);
ll ha= 1<<16;
for(ll i=2;i::iterator i=data.begin();i!=data.end();i++)
{
printf("%llu\n",*i);
}
return 0;
}