原题链接:https://ac.nowcoder.com/acm/contest/1838/A
思路: 看着像是一道斐波那契数列题,其实是一道规律题,可以发现,该序列以 “奇奇偶” 的规律一直循环着。
Code(C++):
#include
using namespace std;
int main(){
long long n;
while(cin>>n){
if(n%3==0)
cout<<"\"odd\""<<endl;
else
cout<<"\"even\""<<endl;
}
return 0;
}
原题链接:https://ac.nowcoder.com/acm/contest/1838/B
思路: 一开始的思路是从 a 串的后面寻找 b 串第一个字符,一找到就标记位置,然后从该位置向右边找,一旦又不相同的就标记并退出循环。样例能过,但就是不知道哪里漏了,不能全部通过。
但有种暴力的方法,就是调用字符串的 substr() 函数,直接在 a 串中枚举所有的字符串,然后与 b 串中从第一个字符开始的相同长度的子串比较,能找到就输出。
Code(C++):
#include
using namespace std;
int main(){
string a,b;
while(cin>>a>>b){
int vis=0;
for(int i=0;i<a.size();i++){
int len = a.size()-i;
string s=a.substr(i,len);
if(s==b.substr(0,len)){
cout<<s<<endl;
vis=1;
break;
}
}
if(!vis)
cout<<"\"NULL!\""<<endl;
}
return 0;
}
原题链接:https://ac.nowcoder.com/acm/contest/1838/C
题意: 给一个花色和14张牌,以下两种情况可以胡牌:
除此之外,每种情况的牌里还不能含有已给出的花色牌,否则不能胡牌。
思路: 用三个数组 s[i], t[i], w[i] 来存相对应花色相对应数字的数量,同时用一个vis 来标记牌中是否已出现已给出的花色,最后判断 vis 以及是否含有胡牌的情况。
Code(C++):
#include
#include
using namespace std;
int t[20],s[20],w[20];
int main(){
int n;
while(cin>>n){
char ch; cin>>ch;
while(n--){
memset(t,0,sizeof(t));
memset(s,0,sizeof(s));
memset(w,0,sizeof(w));
string str; cin>>str;
int vis=1; //标记牌中是否出现已给出的花色
for(int i=0;i<str.length();i++){
if(str[i]==ch) vis=0;
if(str[i]=='W')
w[str[i-1]-'0']++;
if(str[i]=='T')
t[str[i-1]-'0']++;
if(str[i]=='S')
s[str[i-1]-'0']++;
}
//flag1记录是否对对胡,flag2记录是否七对子
int flag1=0,flag2=0;
for(int i=1;i<=9;i++){
if(s[i]==3) flag1++;
if(w[i]==3) flag1++;
if(t[i]==3) flag1++;
if(s[i]==2) flag1++,flag2++;
if(w[i]==2) flag1++,flag2++;
if(t[i]==2) flag1++,flag2++;
}
if((flag1==5 || flag2==7)&& vis)
cout<<"Yes"<<endl;
else
cout<<"No"<<endl;
}
}
return 0;
}
原题链接:https://ac.nowcoder.com/acm/contest/1838/E
题意: 求小于等于 n 的所有质数的阶乘之和。
思路: 这道题有点坑,写着欧拉筛模板题,但其实难点在于取模。某个数字的阶乘 一定是这个数字以及之前数字的倍数。从1 * 2 * 3 * … * a * … * n要模 P,如果a>=p时,a后面再乘一个数%p,数值肯定不变,一定是0,因为这个数是p的整数倍。所以我们要把范围缩小到 min(n, p) 。
Code(C++):
#include
#include
#include
using namespace std;
const int N=1e6+10;
typedef long long ll;
int prime[N],vis[N],x=0;
void isprime() //欧拉筛
{
for(int i=2;i<=N;i++){
if(!vis[i]) prime[x++]=i;
for(int j=0;j<x;j++){
if(i*prime[j]>N) break;
vis[i*prime[j]]=true;
if(i%prime[j]==0) break;
}
}
}
int main(){
isprime();
int t; cin>>t;
while(t--){
int n,p;
cin>>n>>p;
ll ans=0,sum=1;
for(int i=2;i<=min(n,p);i++){ //求阶乘的代码,很美的代码
sum=(sum*i)%p;
if(!vis[i])
ans=(ans+sum)%p;
}
cout<<ans<<endl;
}
return 0;
}
原题链接:https://ac.nowcoder.com/acm/contest/1838/F
题意: 又是一道骗子题,真的后缀自动机我还真不会。询问第一个字符串中是否存在一个后缀 P,使得第二个字符串的任何一个前缀的字典序都大于P。
思路: 第二个字符串前缀字典序要尽量小,那么就是只要看首字符就行了,然后只要跟第一个字符串后缀的首字符比较即可,也就是从后往前遍历第一个字符串。
有点坑的就是这个输出是“YE5”和“N0”!!!
Code(C++):
#include
using namespace std;
int main(){
int t; cin>>t;
while(t--){
string s1,s2;
cin>>s1>>s2;
int vis=0;
for(int i=s1.size()-1;i>=0;i--){
if(s2[0]>s1[i]){
vis=1;
break;
}
}
if(vis) cout<<"YE5"<<endl;
else cout<<"N0"<<endl;
}
return 0;
}
原题链接:https://ac.nowcoder.com/acm/contest/1838/G
思路: 个人感觉这个题目有点难,先把绕迷宫一圈的情况写出来,然后不断递归。
Code(C++):
#include
using namespace std;
int n,m,q;
void Out(int x, int n, int m, int k){
if(n==0 || m==0){
printf("(%d,%d)\n",x,x-1);
return;
}
if(n==1){ //只有一行的情况
if(k<m) printf("(%d,%d)\n",x,x+k);
else printf("(%d,%d)\n",x,x+m-1);
return;
}
if(m==1){ //只有一列的情况
if(k<n) printf("(%d,%d)\n",x+k,m);
else printf("(%d,%d)\n",x+n-1,m);
return;
}
if(k<m){ //k小于m的情况
printf("(%d,%d)\n",x,x+k);
return;
}
k-=m;
if(k<n-1){
printf("(%d,%d)\n",x+k+1,x+m-1);
return;
}
k-=(n-1);
if(k<m-1){
printf("(%d,%d)\n",x+n-1,x+m-2-k);;
return;
}
k-=(m-1);
if(k<n-2){
printf("(%d,%d)\n",x+n-2-k,x);
return;
}
k-=(n-2);
Out(x+1,n-2,m-2,k);
}
int main(){
int t; scanf("%d",&t);
while(t--){
scanf("%d%d%d",&n,&m,&q);
while(q--){
int k; scanf("%d",&k);
Out(1,n,m,k);
}
}
return 0;
}
原题链接:https://ac.nowcoder.com/acm/contest/1838/I
思路: 一道挺复杂的模拟题。看了大佬的代码,思路清晰。
Code(C++):
#include
#include
#include
#include
using namespace std;
struct node{
string name; //队伍名
int ac; //ac题目数量
int sum; //总共用时
int fa[15]; //每题罚时
int cnt[15]; //每题提交次数
int vis[15]; //每题是否ac状态以及在该题所用时间
}a[55];
bool cmp(node x,node y){
if(x.ac!=y.ac) return x.ac>y.ac;
else{
if(x.sum!=y.sum) return x.sum<y.sum;
else return x.name<y.name;
}
}
int main(){
int t; cin>>t;
while(t--){
for(int i=0;i<=50;i++){
a[i].ac = a[i].sum = 0;
memset(a[i].fa,0,sizeof(a[i].fa));
memset(a[i].cnt,0,sizeof(a[i].cnt));
memset(a[i].vis,0,sizeof(a[i].vis));
}
int n,m; cin>>n>>m;
map<string,int> mp;
for(int i=1;i<=m;i++){
cin>>a[i].name;
mp[a[i].name]=i;
}
int q; cin>>q;
while(q--){
int time; char numb;
string id,ans;
cin>>id>>time>>numb>>ans;
if(a[mp[id]].vis[numb-'A']) continue;
else if(ans=="Accepted"){
a[mp[id]].vis[numb-'A']=time;
a[mp[id]].cnt[numb-'A']++;
a[mp[id]].ac++;
a[mp[id]].sum+=(a[mp[id]].fa[numb-'A']+time);
}
else if(ans=="Compilation-Error") continue;
else{
a[mp[id]].cnt[numb-'A']++;
a[mp[id]].fa[numb-'A']+=20;
}
}
sort(a+1,a+1+m,cmp);
int rank=1;
for(int i=1;i<=m;i++){
if(i!=1 && a[i].ac==a[i-1].ac && a[i].sum==a[i-1].sum)
cout<<rank;
else{
rank=i;
cout<<rank;
}
cout<<' '<<a[i].name<<' '<<a[i].ac<<' '<<a[i].sum<<' ';
for(int j=0;j<n;j++){
if(a[i].vis[j])
cout<<'+'<<a[i].cnt[j]<<'('<<a[i].vis[j]<<')'<<' ';
else
cout<<'-'<<a[i].cnt[j]<<' ';
}
cout<<endl;
}
if(t) cout<<endl;
}
return 0;
}
原题链接:https://ac.nowcoder.com/acm/contest/1838/J
思路: 直接暴力两层遍历查找,并不断判断更新 c-a 的值。
Code(C++):
#include
using namespace std;
int main(){
int t; cin>>t;
while(t--){
int n; cin>>n;
int a=0,b=0,c=1e7;
for(int i=2;i*i*i<=n;i++){
if(n%i==0){
for(int j=i;j*j<=n/i;j++){
if(n/i%j==0){
if(c-a>n/i/j-i)
a=i,b=j,c=n/i/j;
}
}
}
}
if(c==1e7) cout<<"No solution"<<endl;
else cout<<n<<'='<<a<<'*'<<b<<'*'<<c<<endl;
}
return 0;
}
原题链接:https://ac.nowcoder.com/acm/contest/1838/K
思路: 先写个程序暴力把所有符合情况的梅森素数输出,然后挑前五个直接输出即可。
Code(C++):
#include
using namespace std;
int main(){
cout<<3<<" "<<7<<" "<<31<<" "<<127<<" "<<8191;
return 0;
}
原题链接:https://ac.nowcoder.com/acm/contest/1838/L
思路: 题目不难,就是题意的理解有点难度。只要四个角存在不能走的,也就是两个箭头都指向某个角,就输出 “Sad” ,否则输出 “Happy”。
Code(C++):
#include
using namespace std;
int main(){
int t; cin>>t;
while(t--){
int n,m;
cin>>n>>m;
string a,b;
cin>>a>>b;
int vis=1;
if(a[0]=='0'&&b[m-1]=='0')
vis=0;
if(a[0]=='1'&&b[0]=='0')
vis=0;
if(a[n-1]=='1'&&b[0]=='1')
vis=0;
if(a[n-1]=='0'&&b[m-1]=='1')
vis=0;
if(vis) cout<<"Happy"<<endl;
else cout<<"Sad"<<endl;
}
return 0;
}
原题链接:https://ac.nowcoder.com/acm/contest/1838/M
题意: 求所有小于等于 n 的素数的倒数之和。
思路: 这道题数太大了,直接模拟肯定暴力,那么可以先打表找规律,即分界点,直接输出,时间复杂度就变成了O(1) 。
Code(C++):
/*
#include
using namespace std;
const int N=1e6+10;
int prime[N],vis[N],x=0;
void isprime(){ //欧拉筛
for(int i=2;i<=N;i++){
if(!vis[i]) prime[x++]=i;
for(int j=0;jN) break;
vis[i*prime[j]]=true;
if(i%prime[j]==0) break;
}
}
}
int main(){
int t; cin>>t;
isprime();
while(t--){
int n; cin>>n;
double ans=0.0;
for(int i=2;i<=n;i++){
if(!vis[i]){
ans+=1.0/i;
printf("%d %.0lf\n",i,ans);
}
}
}
return 0;
}
*/
#include
using namespace std;
int main(){
int t; cin>>t;
while(t--){
int n; cin>>n;
if(n<3) cout<<0<<endl;
else if(n<29) cout<<1<<endl;
else if(n<11789) cout<<2<<endl;
else cout<<3<<endl;
}
return 0;
}