A.Java vs C++回到顶部
题意
给一个字符串,问是C形式还是Java形式,不合法输出Error
题解
有点坑,需要注意'_'在开头和某尾,Java形式不能出现'_',C形式不能出现大写,不能出现连续两个'_',复杂度O(n)
代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 int checkjava(string s){ 5 if('A'<=s[0]&&s[0]<='Z')return false; 6 for(int i=0;s[i];i++){ 7 if(s[i]=='_')return false; 8 } 9 return true; 10 } 11 int checkcpp(string s){ 12 if(s[0]=='_')return false; 13 for(int i=0;s[i];i++){ 14 if('A'<=s[i]&&s[i]<='Z')return false; 15 } 16 for(int i=1;s[i];i++){ 17 if(s[i]=='_'&&s[i-1]=='_')return false; 18 } 19 if(s[s.size()-1]=='_')return false; 20 return true; 21 } 22 int main(){ 23 string s; 24 while(getline(cin,s)){ 25 if(checkjava(s)){ 26 for(int i=0;s[i];i++){ 27 if('A'<=s[i]&&s[i]<='Z')cout<<"_"<<(char)(s[i]+32); 28 else cout<<s[i]; 29 } 30 }else if(checkcpp(s)){ 31 for(int i=0;s[i];i++){ 32 if(s[i]=='_')continue; 33 if(i&&s[i-1]=='_')cout<<(char)(s[i]-32); 34 else cout<<s[i]; 35 } 36 }else{ 37 cout<<"Error!"; 38 } 39 cout<<' '; 40 } 41 return 0; 42 }
B.数据结构实验:压缩对称矩阵回到顶部
题意
给一个对称矩阵,存一半,给定(i,j)输出
题解
存下半,如果i>j那么交换两个数,下标通过观察可以知道是一个等差+一个偏移量,计算得到i*(i-1)/2+j-1
代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 void Zip(int a[100][100],int n,int b[]){ 5 int i,j,index=0; 6 for(i=0;i<n;i++) 7 for(j=0;j<=i;j++) 8 b[index++]=a[i][j]; 9 } 10 int Index(int i,int j){ 11 if(i<j)swap(i,j); 12 //printf("i=%d j=%d index=%d ",i,j,i*(i-1)/2+j-1); 13 return i*(i-1)/2+j-1; 14 }
C.数据结构实验:二叉树倾斜度回到顶部
题意
给一棵树,倾斜度就是每个节点左右儿子子树和的差的绝对值
题解
一个dfs,dfs的同时再写两个dfs用于统计左右子树的和,由于N只有512,这样做也不会超时,复杂度O(n^2)
代码
1 int lson(struct TreeNode* root){ 2 int sum=0; 3 if(root->left!=NULL)sum+=root->left->val+lson(root->left); 4 if(root->right!=NULL)sum+=root->right->val+lson(root->right); 5 return sum; 6 } 7 int rson(struct TreeNode* root){ 8 int sum=0; 9 if(root->left!=NULL)sum+=root->left->val+rson(root->left); 10 if(root->right!=NULL)sum+=root->right->val+rson(root->right); 11 return sum; 12 } 13 int findTilt(struct TreeNode* root){ 14 int sum=0; 15 int lsum=(root->left!=NULL?root->left->val+lson(root->left):0); 16 int rsum=(root->right!=NULL?root->right->val+rson(root->right):0); 17 //printf("%d %d %d %d ",root->val,lsum,rsum,sum); 18 sum+=abs(rsum-lsum); 19 if(root->left!=NULL)sum+=findTilt(root->left); 20 if(root->right!=NULL)sum+=findTilt(root->right); 21 return sum; 22 }
D.C++实验:栈类模板回到顶部
题意
实现一个栈模板
题解
template<class T,int Size>
class MyStack{
private:
public:
}
这个套路,也不是很难,注意这里top为空的时候,需要throw "Empty",复杂度O(1)
代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 template<class T,int SIZE> 5 class Stack { 6 int a[11],top; 7 public: 8 Stack(){ 9 top=0; 10 } 11 void Push(int x){ 12 if(top==10)cout<<"Full "; 13 else a[++top]=x; 14 } 15 int Top(){ 16 string s="Empty"; 17 if(top==0) throw s; 18 else return a[top]; 19 } 20 void Pop(){ 21 if(top==0)cout<<"Empty "; 22 else top--; 23 } 24 };
E.Crosswords回到顶部
题意
给6个长度为3的字符串,问是否可以选出3个使得,横竖出现的恰好是6个字符串
题解
模拟,暴力判断,复杂度O(6^4)
代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 string sb[10],s[10]; 5 map<string,int>sma,smb; 6 bool check(){ 7 smb=sma; 8 string prep; 9 for(int i=0;i<3;i++){ 10 if(smb[sb[i]]>0)smb[sb[i]]--; 11 else return 0; 12 prep=sb[0][i];prep+=sb[1][i];prep+=sb[2][i]; 13 if(smb[prep]>0)smb[prep]--; 14 else return 0; 15 } 16 return 1; 17 } 18 int main(){ 19 for(int i=0;i<6;i++)cin>>s[i],sma[s[i]]++; 20 int f[]={0,1,2,3,4,5}; 21 for(int i=0;i<6;i++) 22 for(int j=0;j<6;j++) 23 for(int k=0;k<6;k++){ 24 if(i!=j&&j!=k){ 25 sb[0]=s[i]; 26 sb[1]=s[j]; 27 sb[2]=s[k]; 28 if(check()){ 29 cout<<sb[0]<<' '<<sb[1]<<' '<<sb[2]<<endl; 30 return 0; 31 } 32 } 33 } 34 cout<<"0 "; 35 return 0; 36 }
F.Kannyi 的easy problem回到顶部
题意
给个n,计算[1,n]中2^n-1有多少个能被7整除
题解
每左移三位可以被7整除,所以答案就是n/3,复杂度O(1)
代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 #define LL long long 5 int main(){ 6 LL n; 7 while(scanf("%lld",&n)!=EOF,n){ 8 printf("%lld ",n/3); 9 } 10 return 0; 11 }
G.Modular Inverse回到顶部
题意
ax同余1(mod p),给定a((0,1000]),p([0,1000])求出x
题解
很明显的exgcd,ax+by=gcd(a,b)
构造ax+py=1,当gcd(a,p)不等于1时无解
求出特解为x,由于要保证x>0,可以不断加上p/gcd(a,p),复杂度O(logn)
PS:ax同余1(mod p)
->ax%p=(py+1)%p
->ax%p=py%p+1
->ax+py同余1(mod p)(+和-一样)
ax+by=c有解的条件是c%gcd(a,p)是否等于0
那么上面有解的条件就是gcd(a,p)是否等于1
代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 ll exgcd(ll a,ll b,ll &x,ll &y) 5 { 6 if(b==0){x=1;y=0;return a;} 7 ll r=exgcd(b,a%b,x,y); 8 ll t=x;x=y;y=t-a/b*y; 9 return r; 10 } 11 int main() 12 { 13 int t; 14 scanf("%d",&t); 15 while(t--) 16 { 17 ll a,p,x,y; 18 scanf("%lld%lld",&a,&p); 19 ll gc=exgcd(a,p,x,y); 20 if(gc!=1)printf("Not Exist "); 21 else 22 { 23 while(x<=0)x+=p/gc; 24 printf("%lld ",x); 25 } 26 } 27 return 0; 28 }
H.桃子的可达数回到顶部
题意
f[x]=x+1去掉末尾的0,问f[f[x]]循环会出现多少个不同的数
题解
模拟,存入unordered_map判重,复杂度O(100)
代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 int t; 7 scanf("%d",&t); 8 while(t--){ 9 int n; 10 scanf("%d",&n); 11 unordered_map<int,int>ma; 12 do{ 13 if(ma.count(n))break; 14 ma[n]=1; 15 n++; 16 while(n!=0&&n%10==0)n/=10; 17 }while(1); 18 printf("%d ",ma.size()); 19 } 20 return 0; 21 }
I.Lagrange's Four-Square Theorem回到顶部
题意
计算有多少个不超过4个平方数之和等于n([1,32768])
题解
可知182*182>32768,那么直接182^4+一些剪枝,复杂度O(14089082≈1.4e7)
PS:dp[i][j]代表值为i,需要j个数的平方相加得到,转移dp[i][j+1]+=dp[i-val*val][j],复杂度O(15752792≈1.5e7),感谢zzl
代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 int n,dp[32768]; 5 int main(){ 6 for(int i=1;i<=182;i++){ 7 dp[i*i]++; 8 for(int j=i;j<=182;j++){ 9 if(i*i+j*j>32768)break; 10 dp[i*i+j*j]++; 11 for(int k=j;k<=182;k++){ 12 if(i*i+j*j+k*k>32768)break; 13 dp[i*i+j*j+k*k]++; 14 for(int l=k;l<=182;l++){ 15 if(i*i+j*j+k*k+l*l>32768)break; 16 dp[i*i+j*j+k*k+l*l]++; 17 } 18 } 19 } 20 } 21 while(scanf("%d",&n)!=EOF,n){ 22 printf("%d ",dp[n]); 23 } 24 return 0; 25 }
1 #include <bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const int N=1<<15; 5 int f[N+5][5]; 6 int main() { 7 f[0][0]=1; 8 for(int i=1;i<=182;i++) { 9 for(int j=i*i;j<=N;j++) { 10 for(int k=0;k<4;k++) { 11 f[j][k+1]+=f[j-i*i][k]; 12 } 13 } 14 } 15 int n; 16 while(~scanf("%d",&n),n) { 17 printf("%d ",f[n][1]+f[n][2]+f[n][3]+f[n][4]); 18 } 19 return 0; 20 }
J.New Game回到顶部
题意
n([1,100000])次操作,每次给一对数(a,b),a、b均小于等于100,问每次操作后,求出某个两两匹配,输出ai+bj最大值最小
题解
可以发现a、b很小,肯定从a、b下手,让ai+bj最小,那么肯定是ai最小的+bj最大的,ai第二小+bj第二大
那么就可以通过pa指针和pb指针,每次都比较,复杂度O(100n)
代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 int n,a[105],b[105],c[105],d[105]; 5 int main(){ 6 scanf("%d",&n); 7 for(int i=1;i<=n;i++){ 8 int x,y; 9 scanf("%d%d",&x,&y); 10 a[x]++;b[y]++; 11 for(int j=1;j<=100;j++)c[j]=a[j],d[j]=b[j]; 12 int pa=1,pb=100,maxx=0; 13 while(pa<=100&&c[pa]==0)pa++; 14 while(pb>=1&&d[pb]==0)pb--; 15 while(pa<=100&&pb>=1){ 16 if(c[pa]>d[pb])c[pa]-=d[pb],d[pb]=0; 17 else if(c[pa]<d[pb])d[pb]-=c[pa],c[pa]=0; 18 else c[pa]=d[pb]=0; 19 //printf("i=%d pa=%d pb=%d ",i,pa,pb); 20 maxx=max(maxx,pa+pb); 21 while(pa<=100&&c[pa]==0)pa++; 22 while(pb>=1&&d[pb]==0)pb--; 23 } 24 printf("%d ",maxx); 25 } 26 return 0; 27 }