比赛链接:https://ac.nowcoder.com/acm/contest/331#question
A 判断能不能形成三角形就可以,如果不能形成三角形那么最短距离就是起点和终点距离减去L1+L2
#include<bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
int main()
{
double x,y,l3;
int l1,l2, t;
std::ios::sync_with_stdio(false);
cin >> l1 >> l2;
cin >> t;
while(t--)
{
cin >> x >> y;
l3 = sqrt((double)x*x+y*y);
if(l3 > l1 && l3 >l2)
{
if(l1+l2>=l3)
{
printf("0.000000\n");
}
else
{
printf("%.6f\n", l3-l1-l2);
}
}
else if(l2 > l1 && l2 >l3)
{
if(l1+l3>=l2)
{
printf("0.000000\n");
}
else
{
printf("%.6f\n", l2-l1-l3);
}
}
else if(l1 > l3 && l1 >l2)
{
if(l2+l3>=l1)
{
printf("0.000000\n");
}
else
{
printf("%.6f\n", l1-l2-l3);
}
}
}
return 0;
}
B: 四个方向搜索一下就行,看了下别人的代码 才会写,这个方法很妙~
#include<bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
set<pair<int,int> >mp[2];
int d[8][2]={-1,0,1,0,0,-1,0,1,-1,-1,1,1,1,-1,-1,1},n,m,comp;
int access(int x,int y)
{
if(x<=n&&y<=n&&x>0&&y>0)
return 1;
return 0;
}
int DFS(int x,int y,int num)
{
int xx, yy,ans = 0,i;
xx=x,yy=y;
for(i=0;i<4;i++)
{
xx=xx+d[num][0];
yy=yy+d[num][1];
if(access(xx,yy)&&mp[comp].count(make_pair(xx,yy)))
ans++;
else break;
}
return ans;
}
int main()
{
std::ios::sync_with_stdio(false);
int i,x,y,ans;
cin>>n>>m;
while(m--)
{
comp=m%2;
cin>>x>>y;
mp[comp].insert(make_pair(x,y));
if(mp[comp].size()<5&&comp%2==1) {cout<<"N"<<endl;continue;}
for(i=0;i<8;i+=2)
{
ans=DFS(x,y,i)+DFS(x,y,i+1);
if(ans>=4)break;
}
if(ans>=4)cout<<"Y"<<endl;
else cout<<"N"<<endl;
}
return 0;
}
C: 主要是要知道怎么走是最短路就行
n或m等于1 就一直走
n或m等于2 就是
其他情况就是 不过这里要判断 一下是横着走还是竖着走 有个条件就是(n/2)*(m-1)<=(m/2)*(n-1) 不过我也不知道为什么是这样判断,如果有知道的还请告知Thanks♪(・ω・)ノ
#include<bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
char mp[1005][1005];
int main()
{
std::ios::sync_with_stdio(false);
int n,m,k,stx=1,sty=1,enx=1,eny=1,i,j,flag=0;
cin>>n>>m>>k;
for(i=1;i<=n;i++){
for(j=1;j<=m;j++)
{
mp[i][j]='x';
}
}
mp[enx][eny]='.';
if(n==1){
for(i=2;i<=k+1;i++)
{
mp[1][i]='.';
eny++;
}
}
else if(m==1){
for(i=2;i<=k+1;i++)
{
mp[i][1]='.';
enx++;
}
}
else if(n==2){
while(k)
{
if(k) enx++,k--,mp[enx][eny]='.';
if(k) eny++,k--,mp[enx][eny]='.';
if(k) eny++,k--,mp[enx][eny]='.';
if(k) enx--,k--,mp[enx][eny]='.';
if(k) eny++,k--,mp[enx][eny]='.';
if(k) eny++,k--,mp[enx][eny]='.';
}
}
else if(m==2){
while(k)
{
if(k) eny++,k--,mp[enx][eny]='.';
if(k) enx++,k--,mp[enx][eny]='.';
if(k) enx++,k--,mp[enx][eny]='.';
if(k) eny--,k--,mp[enx][eny]='.';
if(k) enx++,k--,mp[enx][eny]='.';
if(k) enx++,k--,mp[enx][eny]='.';
}
}
else{
if((n/2)*(m-1)<=(m/2)*(n-1)){
while(k)
{
while(eny<m&&k) eny++,k--,mp[enx][eny]='.';
if(k) enx++,k--,mp[enx][eny]='.';
if(k) enx++,k--,mp[enx][eny]='.';
while(eny>1&&k) eny--,k--,mp[enx][eny]='.';
if(k) enx++,k--,mp[enx][eny]='.';
if(k) enx++,k--,mp[enx][eny]='.';
}
}
else{
while(k)
{
while(enx<n&&k) enx++,k--,mp[enx][eny]='.';
if(k) eny++,k--,mp[enx][eny]='.';
if(k) eny++,k--,mp[enx][eny]='.';
while(enx>1&&k) enx--,k--,mp[enx][eny]='.';
if(k) eny++,k--,mp[enx][eny]='.';
if(k) eny++,k--,mp[enx][eny]='.';
}
}
}
cout<<stx<<" "<<sty<<endl;
cout<<enx<<" "<<eny<<endl;
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
cout<<mp[i][j];
}
cout<<endl;
}
return 0;
}
D: 把起点和终点还有可以传送的点全部放进vector容器里
然后排序,去重
有一个三重循环,前面两重循环是循环每个点,最后一重循环就是判断这两个点之间有没有传送法阵,如果有的话
就是 dp[j]=min(dp[i]+1,dp[j]);
后面 dp[j] = min(dp[i] + __builtin_popcount(mp[j] - mp[i]), dp[j]); 就是i,j 两点的差 换成二进制中1的个数就是要走的路程
最后输出
#include<bits/stdc++.h>
using namespace std;
#define ll long long int
const int INF = 0x3f3f3f3f;
int a[10005],b[10005];
vector<int>mp;
int dp[10005];
int main()
{
std::ios::sync_with_stdio(false);
int n,k,i,j,p;
cin>>n>>k;
mp.push_back(1);
mp.push_back(n);
for(i=0;i<k;i++)
{
cin>>a[i]>>b[i];
mp.push_back(a[i]);
mp.push_back(b[i]);
}
sort(mp.begin(),mp.end());
mp.erase(unique(mp.begin(),mp.end()),mp.end());
memset(dp,INF,sizeof(dp));
dp[0]=0;
for(i=0;i<mp.size();i++)
{
for(j=i+1;j<mp.size();j++)
{
for(p=0;p<k;p++)
{
if(mp[i]==a[p]&&mp[j]==b[p])
{
dp[j]=min(dp[i]+1,dp[j]);
}
}
dp[j] = min(dp[i] + __builtin_popcount(mp[j] - mp[i]), dp[j]);
}
}
cout<<dp[mp.size()-1]<<endl;
return 0;
}
F: 看了很久才看懂题解
首先题目意思是说在子矩阵中的数字随意排列组合,有多少个子矩阵可以构成回文串
根据异或的性质,没有先后顺序,异或两次相当于没有异或
所以我们维护一下前缀异或
这里要注意
所以方法就是这样去判断是否是回文串,pre数组就是记录前缀异或的 num数组就是记录异或值出现的次数
还有一点就是要分组成回文串的是奇数还是偶数
上面那张图是偶数的情况
奇数的情况就是多了一个数字,只出现了一次,这一串回文串最后异或出来的结果就是这个只出现了一次的数字
所以我们循环一下0-9十个数字就行
#include<bits/stdc++.h>
using namespace std;
#define ll long long int
const int INF = 0x3f3f3f3f;
char mp[2][1000005];
int pre[3][1000005];
ll num[3][1000005];
int main()
{
// std::ios::sync_with_stdio(false);
int n,i,j;
ll ans=0;
scanf("%d",&n);
memset(num,0,sizeof(num));
memset(pre,0,sizeof(pre));
scanf("%s",mp[0]+1);
scanf("%s",mp[1]+1);
num[0][0]=num[1][0]=num[2][0]=1;
for(i=1;i<=n;i++)
{
pre[0][i]=pre[0][i-1]^(1<<(mp[0][i]-'0'));
pre[1][i]=pre[1][i-1]^(1<<(mp[1][i]-'0'));
pre[2][i]=pre[2][i-1]^(1<<(mp[0][i]-'0'))^(1<<(mp[1][i]-'0'));
ans+=num[0][pre[0][i]]+num[1][pre[1][i]]+num[2][pre[2][i]];//子矩阵中的数字是偶数时
// cout<<"qqq "<<pre[0][i]<<" "<<pre[1][i]<<" "<<pre[2][i]<<endl;
// cout<<"www "<<num[0][pre[0][i]]<<" "<<num[1][pre[1][i]]<<" "<<num[2][pre[2][i]]<<endl;
// cout<<"111 "<<ans<<endl;
for(j=0;j<10;j++)
{
ans+=num[0][pre[0][i]^(1<<j)]+num[1][pre[1][i]^(1<<j)]+num[2][pre[2][i]^(1<<j)];//奇数个数字构成回文串
// cout<<"qqq "<<num[0][pre[0][i]^(1<<j)]<<" "<<num[1][pre[1][i]^(1<<j)]<<" "<<num[2][pre[2][i]^(1<<j)]<<endl;
// cout<<"222 "<<ans<<endl;
}
num[0][pre[0][i]]++;
num[1][pre[1][i]]++;
num[2][pre[2][i]]++;
}
cout<<ans<<endl;
return 0;
}
G: 打表, 不过这个方法真是妙呀!
#include<bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 1000000;
int prime[1000005],ans[1000005];
void is_prime()
{
int i, j;
memset(prime,0,sizeof(prime));
memset(ans,INF,sizeof(ans));
for(i = 1; i <= maxn; i++)
{
for(j = i; j <= maxn; j+=i)
{
prime[j]++;
}
ans[prime[i]] = min(ans[prime[i]], i);
}
}
int main()
{
std::ios::sync_with_stdio(false);
is_prime();
int t,n;
cin >> t;
while(t--)
{
cin >> n;
if(ans[n]<INF)
cout << ans[n] << endl;
else cout << "-1" << endl;
}
return 0;
}
I:直接按照题意模拟
#include<bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
string str[505];
int d[4][2]={{-1,0},{0,1},{1,0},{0,-1}},n,m;
int access(int x, int y)
{
if(x<n&&y<m&&x>=0&&y>=0)
return 1;
return 0;
}
int main()
{
std::ios::sync_with_stdio(false);
int posi,xx,yy,i,flag;
while(cin >> n >> m)
{
for(i = 0; i < n; i++)
cin >> str[i];
posi = 2;
flag = 0;
for(i = 0; i < m; i++)
{
posi = 2;
xx = 0;
yy = i;
flag = 0;
while(access(xx,yy)&&!flag)
{
while(access(xx,yy)&&str[xx][yy]=='.')
{
xx=xx+d[posi][0];
yy=yy+d[posi][1];
}
// cout << "tttt " << xx << " " << yy << endl;
if(posi==2)
{
if(xx>n-1)
{
flag = 1;
cout << (yy+1) << endl;
}
}
if(flag) break;
if(access(xx,yy)&&str[xx][yy]=='\\')
{
if(posi==0)
posi=3;
else if(posi==1)
posi=2;
else if(posi==2)
posi=1;
else if(posi==3)
posi=0;
}
else if(access(xx,yy)&&str[xx][yy]=='/')
{
if(posi==0)
{
// cout << "0000000" << endl;
posi=1;
}
else if(posi==1)
{//cout << "1111111" << endl;
posi=0;
}
else if(posi==2)
{//cout << "2222222" << endl;
posi=3;
}
else if(posi==3)
{
// cout << "333333" << endl;
posi=2;
}
}
xx=xx+d[posi][0];
yy=yy+d[posi][1];
// cout << xx << " " << yy << endl;
if(posi==2)
{
if(xx>n-1)
{
flag = 1;
cout << (yy+1) << endl;
}
}
if(flag) break;
}
if(!flag)cout << "-1" << endl;
}
}
return 0;
}
J : 把数字换成二进制,A , B 的每一位分别是(0,0)(1,0)(0,1) 是满足情况,所以是3^m;
#include<bits/stdc++.h>
using namespace std;
#define ll long long int
const int INF = 0x3f3f3f3f;
const int mod = 998244353;
ll qpow(ll a,ll b)
{
ll res = 1;
while(b){
if(b%2!=0){
res *= a; res %= mod;
}
a *= a; a%=mod; b /= 2;
}
return res;
}
int main()
{
std::ios::sync_with_stdio(false);
int m;
while(cin >> m)
{
cout << qpow(3,m) << endl;;
}
return 0;
}