1009,直接贪心,只要让后面的尽量小,第一位和第二位尽量大即可。
1011,直接统计奇数的字母的个数,然后用偶数的个数平均分配到它们上面即可。代码如下:
1 #include2 #include 3 #include 4 using namespace std; 5 6 int main() 7 { 8 int T; 9 scanf("%d",&T);10 while(T--)11 {12 int n;13 int odd = 0, even = 0;14 scanf("%d",&n);15 for(int i=1;i<=n;i++)16 {17 int t;18 scanf("%d",&t);19 if(t % 2)20 {21 odd ++;22 even += (t - 1) / 2;23 }24 else even += t / 2;25 }26 if(odd == 0)27 {28 printf("%d\n",even << 1);29 }30 else31 {32 printf("%d\n",even / odd * 2 + 1);33 }34 }35 }
1001,用二次函数做即可,把阿尔法看做一个未知数。分析过程如下:
代码如下:
1 #include2 #include 3 #include 4 using namespace std; 5 typedef long long ll; 6 7 int main() 8 { 9 int T;10 scanf("%d",&T);11 while(T--)12 {13 ll sum = 0, sum2 = 0;14 int n;15 scanf("%d",&n);16 for(int i=1;i<=n;i++)17 {18 int t;19 scanf("%d",&t);20 if(t<0) t = -t; // 全部值都变正21 sum += t;22 sum2 += (ll)t*t;23 }24 sum *= sum;25 if(sum == 0)26 {27 printf("I64%d/%d\n",sum2,1);28 continue;29 }30 ll gd = __gcd(sum,(ll)n);31 if(gd > 1)32 {33 sum /= gd;34 n /= gd;35 }36 sum2 *= n;37 sum2 -= sum;38 if(sum2 == 0)39 {40 printf("%d/%d\n",0,1);41 continue;42 }43 gd = __gcd(sum2,(ll)n);44 if(gd > 1)45 {46 sum2 /= gd;47 n /= gd;48 }49 printf("%I64d/%d\n",sum2,n);50 }51 }
1012,题意是匹配串和原串去匹配,原串的相应区间可以对某些位置进行操作。设位置x是可以操作的,那么x和它下一个位置进行交换;同时,两个x之间的间隔必须大于等于1。直接暴力即可,代码如下:
1 #include2 using namespace std; 3 4 char s[(int)1e5+5],t[5000+5]; 5 char ans[(int)1e5+5]; 6 int n,m; 7 8 bool isok(int pos) 9 {10 int j = 1;11 for(int i=pos;i<=pos+m-1;)12 {13 if(s[i] == t[j])14 {15 i++,j++;16 }17 else18 {19 20 if(i == pos+m-1) return false;21 if(s[i] != t[j+1] || s[i+1] != t[j]) return false;22 else i += 2,j += 2;23 }24 }25 return true;26 }27 28 int main()29 {30 int T;31 scanf("%d",&T);32 while(T--)33 {34 scanf("%d%d",&n,&m);35 scanf("%s",s+1);36 scanf("%s",t+1);37 for(int i=1;i<=n;i++) ans[i] = '0';38 for(int i=1;i+m-1<=n;i++)39 {40 if(isok(i)) ans[i] = '1';41 else ans[i] = '0';42 }43 for(int i=1;i<=n;i++)44 {45 printf("%c",ans[i]);46 }47 puts("");48 }49 }
1005,找出共线的点的集合(集合内点的个数大于等于2,可以是重点)。最初的做法是,找出所有的直线方程,统计这上面的点的个数,然后这条线上的集合的个数就是C(2,m)+C(3,m)+...+C(m,m) = 2^m - m - 1。但是我们实现用了大量的map,可能是因为这一点,超时了。TLE的代码如下:
1 #include2 #include 3 #include 4 #include
看了标程以后觉得他的方法很好。大概是这样子的:先对所有的点按照x,y的大小排序,然后对每一个点,算出包含了这个点的的集合的个数。具体见代码和注释:
1 #include2 typedef long long ll; 3 using namespace std; 4 const int N = 1000 + 50; 5 const int mod = (int)1e9 + 7; 6 7 struct point 8 { 9 int x, y;10 point() {}11 point(int _x, int _y): x(_x), y(_y) {}12 point operator - (const point & temp) const13 {14 return point(x - temp.x, y - temp.y); 15 }16 bool operator < (const point & temp) const17 {18 return x < temp.x || (x == temp.x && y < temp.y);19 }20 bool operator == (const point & temp) const21 {22 return x == temp.x && y == temp.y;23 }24 void reduce()25 {26 int g = __gcd(abs(x), abs(y));27 if(g) {x /= g; y /= g;}28 }29 } p[N], Q[N];30 31 int pw[N];32 void init()33 {34 pw[0] = 1;35 for(int i = 1; i < N; i++) pw[i] = pw[i-1] * 2 % mod;36 }37 38 void update(int &x, int y)39 {40 x += y;41 if(x >= mod) x -= mod;42 }43 44 void run()45 {46 int n;scanf("%d", &n);47 int ans = 0;48 for(int i = 1; i <= n; i++) scanf("%d%d",&p[i].x, &p[i].y);49 // 先要对所有点排序,不然共线向量会有正负的区别50 sort(p + 1, p + 1 + n);51 for(int i = 1; i <= n; i++) 52 {53 int cnt = 0, tot = 0;54 // cnt 是除了i这个点以外的重点的个数55 // m是 这个点位置以外的点的个数56 for(int j = i + 1; j <= n; j++)57 {58 if(p[i] == p[j]) cnt++;59 else Q[++tot] = p[j] - p[i]; // Q 放的是向量60 }61 update(ans, pw[cnt] - 1); // 这里是对重点们形成集合的贡献62 // 计算方式是选出i这个点,之后从剩下的cnt这么多个点中选出至少一个的种类数63 // 那么,贡献就是C(1,cnt)+C(2,cnt)+...+C(cnt,cnt) = 2^cnt - 164 65 for(int j = 1; j <= tot; j++) Q[j].reduce();66 sort(Q + 1, Q + 1 + tot);67 for(int x = 1, y; x <= tot; x = y)68 {69 for(y = x; y <= tot && Q[x] == Q[y]; y++) ;70 // y 出来的时候已经是 Q[x] != Q[y] 了,因此 y-x 正好是这一个角度上其他的点的个数71 // 这时候,对答案的贡献是,从除了i这个点以外的重点中选出任意个数的点的种类数72 // 和从这个角度上的其他点中选出至少1个点的种类数的乘积73 update(ans, 1LL * pw[cnt] * (pw[y - x] - 1) % mod); 74 }75 }76 printf("%d\n", ans);77 }78 79 int main()80 {81 init();82 int T;scanf("%d", &T);83 while(T--) run();84 return 0;85 }