中山Day5——普及
今天题目真是贼难呐。。。才38。。。
收获:树状数组单个修改
树状数组区间修改
T1:旅行
题意:有n个数,问;从中取任意个数,他们的和为质数的方案数是多少?(n<=50)
暴力模拟即可,这里不讲。
见代码:
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; int n,ans,sum,a[551],b[551]; bool flag[551][10001]; bool pan(int x) { if(x==1) return false; int i=2; while(i<=sqrt(x)) { if(x%i==0) break; else i++; } if(i>sqrt(x)) return true; else return false; } void dfs(int x) { for(int i=b[x-1]+1;i<=n;i++) { if(flag[x][a[i]]==false) { sum+=a[i]; flag[x][a[i]]=true; b[x]=i; if(pan(sum)) { ans++; } dfs(x+1); b[x]=0; sum-=a[i]; } } } bool cmp(int x,int y) { return x<y; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); sort(a+1,a+n+1,cmp); dfs(1); printf("%d",ans); return 0; }
好题哉!!!
T2:神秘山庄
见题:
翠亨村是一个神秘的山庄,并不是因为它孕育了伟人孙中山,更神秘的是山庄里有N只鬼、M只兔子,当然还有你。其中每秒钟:
1. 恰有两个生物遇到。
2. 任意两个生物之间相遇的概率是均等的。
如果两只兔子相遇,没有事情发生;如果两只鬼相遇,他们会互相厮打,最终一起死亡;如果鬼遇到兔子,兔子就会被吃掉;如果鬼遇到你,哈哈。。。。symbol就见不到你了;如果你遇到兔子,那么你可以选择杀或不杀(概率相等)。
问你能活着见symbol的概率。
显然:只有鬼死光了才能获胜。那么兔子就是什么用都没有的了,剩下的,若鬼是奇数,责必死无疑。若鬼是偶数,因为最后人鬼只能活一个,所以概率为1/(n+1)。
见代码:
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; double n,m,a,sum=1; int main() { scanf("%lf%lf",&n,&m); a=m+1+n; if(int(n)%2==0) printf("%.6lf",1/(n+1)); else printf("%.6lf",0); return 0; }
好题哉!!!
T3:幸运锁
有一把幸运锁,打开它将会给你带来好运,但开锁时需要输入一个正整数(没有前导0)。幸运锁有一种运算,对于一个正整数,返回他的相邻两位数字间的差,如1135,运算结果为22(会去掉前导0)
现在已知只有经过反复运算最终结果为7的数才能打开这把锁,给你一个区间[a,b],问该区间中有多少个能打开幸运锁的幸运数。【限制】1<=a<=b<=10^9。
思路:暴力打表,暴力枚举。(据说有大佬用pascal打表AC)
见代码:
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; int a[101],b[101],flag,head; bool pan(int x) { flag=0; while(x!=0) { flag++; b[flag]=x%10; x/=10; } for(int i=1;i<=flag;i++) a[i]=b[flag-i+1]; while(flag>1) { head=1; while(a[1]==0) { for(int j=2;j<=flag;j++) { a[j-1]=a[j]; } flag-=1; if(flag==1) break; } for(int i=1;i<flag;i++) { a[head]=abs(a[i]-a[i+1]); head++; for(int j=i+2;j<=flag;j++) { a[j-1]=a[j]; } flag--; } } if(a[1]==7) return true; return false; } int main() { freopen("lucky.in","r",stdin); freopen("lucky.out","w",stdout); int a1,b1,j,j1=0,ans=0; scanf("%d%d",&a1,&b1); for(int j=a1;j<=b1;j++) if(pan(j)==true) ans++; printf("%d\n",ans); return 0; }
好题哉!!!
T4:简单题
题意:给定一个序列,有两种操作:询问一段区间内的数字和、给一个区间内每个数加一个值。你需要回答每个询问。
思路:一看这题:呦呵!不是线段树区间修改的模板吗,秒做的说。
见代码:
#include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; long long n,q,d,s,c1[100001],sum1[100001],c2[100001],a[100001]; char w; long long lowbit(long long x) { return x&(-x); } long long sum(long long c[],long long x) { long long ret=0; while(x>0) { ret+=c[x]; x-=lowbit(x); } return ret; } void add(long long c[],long long x,long long y) { while(x<=n) { c[x]+=y; x+=lowbit(x); } } int main() { freopen("simple.in","r",stdin); freopen("simple.out","w",stdout); scanf("%ld%ld",&n,&q); for(int i=1;i<=n;i++) { scanf("%ld",&a[i]); sum1[i]=sum1[i-1]+a[i]; } for(int j=1;j<=q;j++) { cin>>w; scanf("%ld%ld",&s,&d); if(int(w)==int('Q')) { long long suml=sum1[s-1]+s*sum(c1,s-1)-sum(c2,s-1); long long sumd=sum1[d]+(d+1)*sum(c1,d)-sum(c2,d); printf("%ld\n",sumd-suml); } else { long long cost; scanf("%ld",&cost); add(c1,s,cost); add(c1,d+1,-cost); add(c2,s,s*cost); add(c2,d+1,-(d+1)*cost); } } return 0; }
好题哉!!!