明天是元旦,今天写写博客总结下这半周收获的一点点东西,另外,也纪念一年2017年的最后一天。有点伤感,有点不舍,但这就是时光,就是青春。每次到这个时候都倍加伤感,感觉虽然我挺笨,而且很蠢,但2017对我真的挺好。
2017学到了许多新知识,度过了许多难忘而且美好的时光,有了点小进步,也认识了许多新朋友。虽然有的时候有些小懒惰,小迷茫,但最终还是找到了前进的方向和几分未来的信心。 每到这个时候,最想留住的是时光,可最留不住的也是时光,这一年发生的事简直就像电影,一幕一幕,一张一张。2017年,我选修了ACM程序设计基础课,开始了我的ACM之旅,也开启了一场难忘的旅行。虽然我属于比较笨的类型,但我至少可以自信的说,2017年我真的有进步,无论从专业知识还是acm,还是到我的为人处事,见识心智,都或多或少有许多进步,许多改变。想想acm和大学时光已经所剩无几,真的不能怠慢,要更加努力,更加扎实,更加积极。必须鼓足干劲,还有寒假集训,明年的比赛,我必须要有质的变化,质的进步。
有点不太像理科生了,那么伤感。进入正题吧。整理一下几道比较重要的题。
牛客网练习赛9 E珂朵莉的数论题
珂朵莉想求:
第x小的正整数v使得其最小的质因数为质数y,即正好有x-1个[1,v-1]之内的正整数满足其最小的质因数为质数y。
若答案超过1000000000则输出0。
拿到这道题一开始感觉就是容斥原理,因为可以用容斥原理dfs出1到n之内有多少以y为最小质因数的个数,然后感觉二分答案找出满足条件的上界。其实思路上也沾边了,但是还是实力太菜,最终没能做出来。
下面是我找到两位大佬的做法,思路大致也差不多。
void init()
{
for(int i=2;i<=maxn;++i)//筛素数
{
if(!prime[i])prime[++prime[0] ]=i;
for(int j=1;j<=prime[0]&&prime[j]<=maxn/i;++j)
{
prime[prime[j]*i]=1;
if(i%prime[j]==0)break;
}
}
}
bool has(int a,int m)//这波暴力令我猝不及防,只是暴力的确实比较巧妙。其实好好算算那个数据大小并没有那么吓人
{
for(int i=1;;++i)
{
if(prime[i]>=m)return false;
if(a%prime[i]==0)return true;
}
}
int get(int a,int b)
{
int cnt=0;
for(int i=a;i<=ma;i+=a)
{
++cnt;
if(has(i,a))--cnt;
if(cnt==b)return i;
}
return 0;
}
int main()
{
init();
int m,n;cin>>m>>n;
if(m==1)cout<<n;
else
{
if((ll)n*n>ma)cout<<0;
else
{
if(n<=3)//分类讨论2和3的情况,其他的直接暴力了,居然可以过
{
if(n==2)
{
ll k=2;
if(k*m>ma)cout<<0;
else cout<<k*m;
}
else
{
m=m*2-1;
ll k=3;
if(k*m>ma)cout<<0;
else cout<<k*m;
}
}
else cout<<get(n,m);
}
}
return 0;
}
下面这算是题解给出的做法
long long maxn=1000000000;
long long prime[20]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71};
long long solve1()//y大于等于5直接时筛出来,方法也是挺巧妙的,这我这是没想到这有点暴力的做法居然可以,还是水平不行。
{
long long i,j,k=1;
if(x==1) return 1;
for(i=2;i<y;i++) if(!p[i])
for(j=i+i;j<=maxn;j+=i) p[j]=1;
for(i=y;i<=maxn;i++){
if(!p[i]){
k++;
if(x==k) return i;
}
}
return 0;
}
long long cal(long long a,long long i)
{
if(prime[i]>=y) return a;
if(a==0) return 0;
return cal(a,i+1)-cal(a/prime[i],i+1);
}
long long solve2(){//当y为2,3,时用二分
long long l=1,r=maxn,mid,sum;
while(l<r){
mid=(l+r)/2;
sum=cal(mid,0);
if(sum<x) l=mid+1;
else r=mid;
}
if(x==cal(l,0)) return l;
return 0;
}
int main(){
scanf("%lld%lld",&x,&y);
maxn/=y;
if(y>=5) ans=solve1();
else ans=solve2();
printf("%lld\n",ans*y);
}
又尝试水了几道期望题
A Dangerous Maze
题目大意: 给你n个门,每次进每个门的概率都是一样的,正数代表你x分钟后可以离开这里,负数代表你x分钟后回到这里。求预期离开的时间。
因为有走错门就失忆这个设定,所以可以直接列方程,解方程就可以,设期望是E,
E = (a1+a2+……+an + (abs(b1)+E)+(abs(b2)+E)+……+(abs(bm)+E))/n 整理得
E = (a1+a2+……+an+abs(b1)+abs(b2)+……+abs(bm))/(n-m);
其实就是解方程。
int gcd(int x,int y)
{
if(y==0)
{
return x;
}
else return gcd(y,x%y);
}
int main()
{
int T,n,x,Case=0;
scanf("%d",&T);
while(T--)
{
int cnt=0,sum=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&x);
if(x<0) cnt++;
sum+=abs(x);
}
cout<<"Case "<<++Case<<": ";
if(cnt==n)//如果全是负数,那就走不出去了
{
cout<<"inf"<<endl;
continue;
}
cnt=n-cnt;
int k=gcd(sum,cnt);
cout<<sum/k<<"/"<<cnt/k<<endl;
}
}