反思总结
真的是太菜了 --__-
A
一看超大数据, 绝逼是找规律
手写出前十个数, 会发现 奇奇偶 …
模3输出…
细节决定成败, 水题上加罚时血亏, A题输出带", 平时做题基本没有遇到过", 走进了思维盲区, 1wa … 就输出一个双引号, 就可以避免20分钟的罚时 …
B
B题, 最长公共子串, 一看题目就开始上模板了, 但是这个和模板不太一样, 需要这个子串还是第二个字符串开头, 于是各种改, 各种wa … 后来仔细想想, 如果是那复杂的板子, 会有人在十几分钟a了? … 于是开始暴力, 思维不缜密wa一次 … 最后终于是暴力找过了
比赛结束以后, 突然想起来, 用 c++ string 成员函数 substr 枚举 第一个字符串的长度不就几行代码搞定??? 马上手写一遍, 接着过了 … 这说明比赛的时候还是要冷静思考, 多思考, 思考明白了再动手
#include<bits/stdc++.h>
using namespace std;
int main ( ) {
string s1, s2;
while ( cin >> s1 >> s2 ) {
int len1 = s1.size(),
len2 = s2.size();
string tmp_s1 = "";
string tmp_s2 = "";
bool ans = false;
for ( int len = len1; len > 0; --len ) {
tmp_s1 = s1.substr( len1-len, len );
tmp_s2 = s2.substr( 0, len);
if ( tmp_s1 == tmp_s2 ) {
ans = true;
break;
}
}
cout << ( ans ? tmp_s1 : "\"NULL!\"" ) << endl;
}
return 0;
}
C
C 题, 并不难, 就是统计个数罢了, 看明白题意, 理解了是很好做的
#include<bits/stdc++.h>
using namespace std;
int sum[4][10];
map<char,int> mp;
int main ( ) {
mp['T'] = 0;
mp['S'] = 1;
mp['W'] = 2;
int T;
char noKind;
while ( cin >> T ) {
cin >> noKind;
while ( T-- ) {
memset ( sum, 0, sizeof ( sum ) );
char num, kind;
for ( int i = 0; i < 14; ++i ) {
cin >> num >> kind;
if ( kind != noKind ) sum[mp[kind]][num-'0']++;
}
int cnt_2 = 0, cnt_3 = 0;
for ( int i = 0; i < 3; ++i ) {
for ( int j = 0; j < 10; ++j ) {
if ( sum[i][j]==2 )
cnt_2++;
else if ( sum[i][j]==3 ) {
cnt_3++;
}
}
}
cout << ( cnt_2==7 || (cnt_2==1&&cnt_3==4) ? "Yes" : "No" ) << endl;
}
}
return 0;
}
E
欧拉筛板子, 难点不是欧拉筛, 而是取模的技巧
如果按题意直接阶乘累加, 会超时,
我们这样来看, 某个数字的阶乘 一定 是这个数字以及之前数字的 倍数 ( 因数分解, 都懂 … )
那么, 假设 n = 1e6; p = 10;
那么, 从第十项开始, 一直到 1e6 每个数的阶乘取模全都是 0, 这样在这一范围内浪费大量时间
于是, 枚举 n 的时候, 只需要枚举到 p, 一旦这个数比 p 还大, 直接 break; 后面全是0, 加和不加有区别嘛
太巧妙了… 反正我是超时了 --_–
#include <bits/stdc++.h>
using namespace std;
#define rg register
#define sc scanf
#define pf printf
typedef long long ll;
const int MAXN = 1e7+10;
bool isp[MAXN]; int su[MAXN]; // su 比 MAXN 小一个数量级合适
void Euler ( int MAXN ) {
register int tot = 0;
memset( isp, true, sizeof(isp) ), isp[0] = false, isp[1]= false;
memset( su, 0, sizeof(su) );
for ( register int i = 2; i <= MAXN; ++i ) {
if ( isp[i] ) su[tot++] = i;
for ( register int j = 0; j<tot&&i*su[j]<=MAXN; ++j ) {
isp[i*su[j]] = false;
if ( !(i%su[j]) ) break;
}
}
}
int main ( ) { // freopen( "F:\\in\\.txt" , "r" , stdin );
int T,
n, p;
Euler( MAXN );
sc( "%d", &T );
while ( T-- ) {
ll sum = 0,
tmp = 1;
sc( "%d%d", &n, &p );
for ( int i = 1; i <= n; ++i ) {
if ( i >= p ) break; // 精辟
tmp = tmp*i%p;
if ( isp[i] ) {
sum = (sum+tmp)%p;
}
}
pf( "%lld\n", sum );
}
return 0 ;
}
F
好一个标题党, 被题意给唬住了, 以为是ac自动机 …
这个大水题隐藏的可真够深的啊 !!!
从第一个字符串中找一个后缀, 永远满足字典序小于 第二个字符串
其实字符串比较大小和数字比较大小没啥区别, 从首位开始比较,
那么只需要遍历一遍第一个字符串, 找一个比第二个字符串小的的字符
这个字符到第一个字符串结尾, 即为第一个字符串的后缀
#include <bits/stdc++.h>
using namespace std;
int main ( ) {
int T;
scanf ( "%d", &T );
while ( T-- ) {
string ss, st;
cin >> ss >> st;
bool ans = false;
for ( int i = 0; ss[i] != '\0'; ++i ) {
if ( ss[i] < st[0] ) {
ans = true;
break;
}
}
cout << ( ans ? "YE5" : "N0" ) << endl;
}
return 0;
K
能化成 2n-1 格式的数是梅森数, 这个数又是素数, 那就是梅森素数, 输出前五个梅森素数…
暴力枚举打表, 记下来, 交代码输出… 这明目张胆的打表 … --_–
L
规律非常重要,
只要发现, 无论电梯怎么安排, 只要外围构成一个环, 那么想到哪儿就可以到哪儿…
于是乎, 两种情况, 顺时针, 逆时针, 两行代码结束 …
if ( sn[0]=='0' && sn[len1-1]=='1' && sm[0]=='0' && sm[len2-1]=='1' ) ans = true;
if ( sn[0]=='1' && sn[len1-1]=='0' && sm[0]=='1' && sm[len2-1]=='0' ) ans = true;
或者仔细看看上下左右01的规律, 一行即可
if ( sn[0]==sm[0] && sn[len1-1]==sm[len2-1] && sn[0]!=sn[len1-1] && sm[0]!=sm[len2-1] ) ans = true;