只有三个整数,A,B,C。满足 0≤a≤100,0≤b≤10,0<c<100 。
一个整数,即 ABmodC 。
2 10 7
2
水题,注意b可以等于0,所以最后还需要对c取模(没看数据范围,WA了)
#include <cstdio> using namespace std; int main() { int a,b,c,ans; while(3==scanf("%d%d%d",&a,&b,&c)) { ans=1; while(b-->0) { ans=(ans*a)%c; } printf("%d\n",ans%c); } return 0; }
有一天,郭铮鹏想去见一见他远在他乡的基友J,并且玩一玩他的Xbox。郭铮鹏和J都生活在笛卡尔坐标下。郭铮鹏的家在点(0,0)而J的家在点(a,b)。郭铮鹏每一次可以横向或者纵向移动一步。也就是说,他能从(x,y)移动到(x+1,y),(x-1,y),(x,y+1)或(x,y-1). 不幸的是,郭铮鹏这个人没有方向感。所以他每一步都随机选择一个方向来行走。郭铮鹏可能凑巧的走着走着又走回了他家。郭铮鹏甚至会到达基友家门口但意识不到,然后继续行走。 幸运的是,郭铮鹏成功地到达了(a,b)。到了之后他和J吹嘘:"我走了s步才走到你家呢"。但J不是很相信郭铮鹏的这句话,他不确定从(0,0)走到(a,b)走s步是否是可能的。你能帮J确定这是否可能吗?
对于每组数据,输出一行,如果无法走到,输出"No",否则输出"Yes"。
5 5 11 10 15 25 0 5 1 0 0 2
No Yes No Yes
水题,(0,0)到(a,b)最少要走a+b步,如果s<abs(a)+abs(b),则必定不能到达,若s>=abs(a)+abs(b),则s与a+b奇偶性相同时(即 s-abs(a)-abs(b) 为偶数),可达,否则不可达。(没看数据范围,又WA了...)
#include <cstdio> #include <algorithm> using namespace std; int main() { int a,b,s; while(3==scanf("%d%d%d",&a,&b,&s)) { if(s<abs(a)+abs(b)) { printf("No\n"); } else { printf("%s\n",((s-abs(a)-abs(b))&1)==0?"Yes":"No"); } } return 0; }
输入由多组数据组成,每组数据一行,为三个整数k,n,w( 1≤k,w≤1000,0≤n≤109 ),分别表示第一个杯垫的售价、郭铮鹏一开始手上的钱数和他想要的杯垫数量(单位:元)。
对于每组数据,输出一个整数,表示郭铮鹏至少需要借的钱,如果他不需要借钱,输出0。
3 17 4
13
这题是某次CF的A题
依旧水题,统计总共需要的钱,然后判断即可
#include <cstdio> #include <algorithm> using namespace std; int main() { int k,n,w,ans; while(3==scanf("%d%d%d",&k,&n,&w)) { ans=(k+w*k)*w/2-n; printf("%d\n",ans<=0?0:ans); } return 0; }
对于每组数据输出一行,按照输入的顺序输出每个学生的排名。每两个整数用一个空格隔开。
3 1 3 3 1 1 5 3 5 3 4 5
3 1 1 1 4 1 4 3 1
排序,然互赋予每个成绩排名即可
数据小,所以每次找最小的标记排名也可
#include <cstdio> #include <algorithm> using namespace std; struct Node { int i,a; bool operator < (const Node& b) const { return a>b.a; } }s[2005]; int n,rnk[2005]; int main() { int cur,cnt; while(1==scanf("%d",&n)) { for(int i=0;i<n;++i) { s[i].i=i; scanf("%d",&s[i].a); } sort(s,s+n); cur=1; cnt=1; rnk[s[0].i]=1; for(int i=1;i<n;++i) { if(s[i].a!=s[i-1].a) { cur+=cnt; cnt=0; } ++cnt; rnk[s[i].i]=cur; } printf("%d",rnk[0]); for(int i=1;i<n;++i) { printf(" %d",rnk[i]); } printf("\n"); } return 0; }
输入由多组数据组成。每组数据一行,包含一个整数n( 1≤n≤109 ),表示图书馆里书的总数。
对于每组数据,输出一个整数,表示给这些书编号需要写的数字位数之和。
13 4
17 4按位数统计数字即可,得用long long,没用debug半天...
int n; long long lim[11]={0,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000,1000000001}; long long ans; int main() { while(1==scanf("%d",&n)) { ans=0; for(long long i=1;i<=10&&lim[i-1]<=n;++i) { if(n>=lim[i]) { ans+=i*(lim[i]-lim[i-1]); } else { ans+=i*(n-lim[i-1]+1); } } printf("%lld\n",ans-1LL); } return 0; }
4 75 150 75 50 3 100 150 250
Yes No
题目大意:给定n个数,每个数a[i]可以变成a[i]*(2^p)*(3^q)(p,q>=0,p,q可取任意值),问这n个数经过变换后是否能相同?
第一反应就是:设所有a[i]的最大公约数为gcd,若要变换后能相同,则a[i]/gcd的质因子只有2和3
若a[i]/gcd还存在其他质因子z,则z无法通过(2^m)*(3^n)获得,则其他数经过变换后必定不能形成与a[i]变换后想等的数
#include <cstdio> #include <algorithm> using namespace std; int n,gcd,a[100005]; bool flag; int main() { while(1==scanf("%d",&n)) { flag=true; scanf("%d",a); gcd=a[0]; for(int i=1;i<n;++i) { scanf("%d",a+i); gcd=__gcd(gcd,a[i]); } for(int i=0;i<n;++i) { a[i]/=gcd; while(a[i]%3==0) { a[i]/=3; } while(a[i]%2==0) { a[i]/=2; } if(a[i]!=1) { flag=false; break; } } printf("%s\n",flag?"Yes":"No"); } return 0; }
————————————————————6题的旅游分割线————————————————————
本来不想写的,但是限于环境问题,3h就写了一道最大流,绝得效率太低,就在最后1h写了一下,发现前6题还挺简单...
估计英文第一题,才是真正的A题
3 abc 1 abcabc 1 abcabc 2
6 15 21题目大意:给定一个只含小写字母的字符串,统计满足限制的子串数目,子串中出现次数最多的字符出现次数不超过k。
正难则反,首先所有子串的数目很容易求出,所以只要求出不符合题意的子串就行
将每个字符每次出现的下标存入队列,当有字符出现次数超过k时,就开始减去不符合的子串,每次只计算以当前字符为结尾的不符合的子串即可,为了不漏掉不符合的,用last表示到当前字符时,存在不符合子串的起始的最靠后的下标,然后不符合的子串数就是last+1
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; int k,len,cur,last; int tail[26]; int q[26][100005]; char s[100005]; long long ans; int main() { int T; scanf("%d",&T); while(T-->0) { scanf("%s%d",s,&k); memset(tail,0,sizeof(tail)); ans=0; last=-1;//last表示存在重复不符合题意的子串的最靠后的起始下标 for(len=0;s[len]!='\0';++len) { cur=s[len]-'a'; q[cur][tail[cur]++]=len; if(tail[cur]>k) { last=max(last,q[cur][tail[cur]-k-1]);//更新最靠后的起始下标 } ans-=last+1;//减去以当前字符为结尾的不符合题意的子串数 } ans+=(1LL+len)*len/2;//最后再加上总的子串数 printf("%lld\n",ans); } return 0; }
1 1 0 1 0 1 1 0 0 0 1 1 1
0.4082 0.5000 0.5000 1.0000 0.6667 0.6667 0.6667一眼就看出来是高中数学解析几何,可以已经忘了...真是悲伤
找了个模版AC掉...
完整三维计算几何模版
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const double EPS=0.000001; typedef struct Point_3D { double x, y, z; Point_3D(double xx = 0, double yy = 0, double zz = 0): x(xx), y(yy), z(zz) {} bool operator == (const Point_3D& A) const { return x==A.x && y==A.y && z==A.z; } }Vector_3D; Point_3D read_Point_3D() { double x,y,z; scanf("%lf%lf%lf",&x,&y,&z); return Point_3D(x,y,z); } Vector_3D operator + (const Vector_3D & A, const Vector_3D & B) { return Vector_3D(A.x + B.x, A.y + B.y, A.z + B.z); } Vector_3D operator - (const Point_3D & A, const Point_3D & B) { return Vector_3D(A.x - B.x, A.y - B.y, A.z - B.z); } Vector_3D operator * (const Vector_3D & A, double p) { return Vector_3D(A.x * p, A.y * p, A.z * p); } Vector_3D operator / (const Vector_3D & A, double p) { return Vector_3D(A.x / p, A.y / p, A.z / p); } double Dot(const Vector_3D & A, const Vector_3D & B) { return A.x * B.x + A.y * B.y + A.z * B.z; } double Length(const Vector_3D & A) { return sqrt(Dot(A, A)); } double Angle(const Vector_3D & A, const Vector_3D & B) { return acos(Dot(A, B) / Length(A) / Length(B)); } Vector_3D Cross(const Vector_3D & A, const Vector_3D & B) { return Vector_3D(A.y * B.z - A.z * B.y, A.z * B.x - A.x * B.z, A.x * B.y - A.y * B.x); } //空间两直线上最近点对 返回最近距离 点对保存在ans1 ans2中 double SegSegDistance(Point_3D a1, Point_3D b1, Point_3D a2, Point_3D b2, Point_3D& ans1, Point_3D& ans2) { Vector_3D v1 = (a1 - b1), v2 = (a2 - b2); Vector_3D N = Cross(v1, v2); Vector_3D ab = (a1 - a2); double ans = Dot(N, ab) / Length(N); Point_3D p1 = a1, p2 = a2; Vector_3D d1 = b1 - a1, d2 = b2 - a2; double t1, t2; t1 = Dot((Cross(p2 - p1, d2)), Cross(d1, d2)); t2 = Dot((Cross(p2 - p1, d1)), Cross(d1, d2)); double dd = Length((Cross(d1, d2))); t1 /= dd * dd; t2 /= dd * dd; ans1 = (a1 + (b1 - a1) * t1); ans2 = (a2 + (b2 - a2) * t2); return fabs(ans); } int main() { int T; Point_3D a1,a2,b1,b2,ans1,ans2; double dis; scanf("%d",&T); while(T-->0) { a1=read_Point_3D(); a2=read_Point_3D(); b1=read_Point_3D(); b2=read_Point_3D(); dis=SegSegDistance(a1,a2,b1,b2,ans1,ans2); printf("%.4lf\n",dis); printf("%.4lf %.4lf %.4lf %.4lf %.4lf %.4lf\n",ans1.x,ans1.y,ans1.z,ans2.x,ans2.y,ans2.z); } return 0; }
3 1 100 500
0 1 5
From 1 to 500, the numbers that include the sub-sequence "96" are "96","196","296","396","496",so the answer is 5.
一道裸的数位DP
官方标程错了,我写的一直WA,看了一个AC的代码,很明显发现有错...
#include <cstdio> using namespace std; int num[25],len; long long n,ans; long long dp[25][3];//dp[i][0]表示长度为i,且不含96的数字个数;dp[i][1]表示长度为i,不含96且最高位为6的数字个数;dp[i][2]表示长度为i,且含有96的数字个数 void Init() { dp[0][0]=1; dp[0][1]=dp[0][2]=0; for(int i=1;i<=20;++i) { dp[i][0]=dp[i-1][0]*10-dp[i-1][1];//长度为i-1且不含96的数字,最高位可加上0~9;但若最高位加上9,而次高位为6则不满足,所以要减去 dp[i][1]=dp[i-1][0];//长度为i-1,不含96的数字,最高位可加上9 dp[i][2]=dp[i-1][2]*10+dp[i-1][1];//长度为i-1且含96的数字,最高位可加上0~9;长度为i-1,不含96且最高位为6,则目前最高位可加上9 } } long long getCnt(long long x) {//返回[1,x]中含有49的数字个数 ++x; ans=len=0; while(x>0) { num[++len]=x%10; x/=10; } num[len+1]=-1; bool flag=false;//表示高位是否出现过96,true表示出现过 for(int i=len;i>=1;--i) {//从最高位开始枚举 ans+=dp[i-1][2]*num[i];//低i-1位中出现96的数字,当前位可取0~(num[i]-1) if(flag) {//如果高位出现过96 ans+=dp[i-1][0]*num[i];//高位出现过96,低i-1位没有出现过96,当前位可取0~(num[i]-1) } if(!flag&&num[i+1]==9&&num[i]>6) { ans+=dp[i-1][0];//高位未出现过96,且上一位为9,当前位大于6,则当前位可以取6,则低i-1为可任取不含96的数字 } if(num[i+1]==9&&num[i]==6) {//若该位与上一位能组成96 flag=true; } } return ans; } int main() { Init(); int T; scanf("%d",&T); while(T-->0) { scanf("%lld",&n); printf("%lld\n",getCnt(n)); } return 0; }
2 1 2 2 3
6 18题目大意:定义在到达(x,y)的花费为c(x,y)
1. if x = 0 or y = 0, c(x,y) = 1
2. if x > 0 and y > 0, c(x,y) = c(x,y-1) + c(x-1,y)
3. if x < 0 or y < 0 c(x,y) = infinite.
每次只能向相邻的一个格子走,求从(0,0)走到(n,m)的最小花费?
大致思路:先手动写上小数据的各个格子的花费,可以看出做左上角开始的副对角线是二项式系数(杨辉三角)
又可以发现,要想花费最少,则必定只走n+m步,可以先贪心地走到(0,m)【n<=m时】 或 (n,0)【n>m时】
则转换为计算组合数了
不妨设n<=m
则答案为:m+1+C(m,1)+C(m+1,2)+…+C(m+n+1,n)=m+C(m,0)+C(m,1)+C(m+1,2)+…+C(m+n,n-1)
利用组合数性质: C(n,m)= C(n,n-m)= C(n-1,m-1)+C(n-1,m)
可得:m+C(m+n+1,n)
随便找了个模版,效率好低,跑了450ms,别人都是50ms...
换了这个模版后,瞬间变成16ms,看来模版的效率不容忽视
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long LL; const LL MOD=1e9+7; LL n,m; LL quick_pow(LL a, LL b) { LL ans = 1; a %= MOD;//防止指数为0时,返回未取模的结果 while(b!=0) { if((b & 1)==1) { ans = ans * a % MOD; } b >>= 1; a = a * a % MOD; } return ans; } LL C(LL n, LL m) { if(n < m) { return 0; } if(n == m) { return 1; } if(m > n - m) {//利用组合数性质,减少运算次数 m=n - m; } LL ans, a = 1, b = 1; for(int i=0; i<m; ++i) { a = (a * (n - i)) % MOD; b = (b * (m - i)) % MOD; } ans = (a * quick_pow(b, MOD-2)) % MOD; return ans; } LL Lucas(LL n, LL m) { LL ans=1; while(m>0) { ans=(ans*C(n % MOD, m % MOD)) % MOD; n/=MOD; m/=MOD; } return ans; } int main() { int T; scanf("%d",&T); while(T-->0) { scanf("%lld%lld",&n,&m); if(n>m) { swap(n,m); } printf("%lld\n",(Lucas(m+n+1,n)+m)%MOD); } return 0; }