problemA:给定一个圆的周长n,初始在位置a,然后走b步,求最后位置在哪?
分析:不想分析。O(1)
代码:
#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<bitset>
#include<math.h>
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
const int N=500100;
const int MAX=151;
const int mod=100000000;
const int MOD1=1000000007;
const int MOD2=1000000009;
const double EPS=0.00000001;
typedef long long ll;
const ll MOD=998244353;
const ll INF=10000000010;
typedef double db;
typedef unsigned long long ull;
int main()
{
int n,m,k;
scanf("%d%d%d", &n, &m, &k);
m=(m+k-1)%n;
printf("%d\n", (m+n)%n+1);
return 0;
}
problemB:给定n个人的信息:名字,赛区编号,赛区选拔成绩。从每个赛区选出成绩最好的2个人来入围。如果这2个人的选择不唯一输出"?"。
分析:结构体排序即可。O(nlogn)
代码:
#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<bitset>
#include<math.h>
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
const int N=100010;
const int MAX=151;
const int mod=100000000;
const int MOD1=1000000007;
const int MOD2=1000000009;
const double EPS=0.00000001;
typedef long long ll;
const ll MOD=998244353;
const ll INF=10000000010;
typedef double db;
typedef unsigned long long ull;
struct node {
int r,num;
char s[15];
}a[N];
int cmd(node x,node y) {
if (x.r!=y.r) return x.r<y.r;
return x.num>y.num;
}
int main()
{
int i,k=0,n,m;
scanf("%d%d", &n, &m);
for (i=1;i<=n;i++) scanf("%s%d%d", a[i].s, &a[i].r, &a[i].num);
sort(a+1,a+n+1,cmd);
for (i=1;i<=n;)
if (i+2>n||a[i].r!=a[i+2].r) {
printf("%s %s\n", a[i].s, a[i+1].s);i+=2;
} else {
if (a[i+1].num==a[i+2].num) printf("?\n");
else printf("%s %s\n", a[i].s, a[i+1].s);
while (i+1<=n&&a[i].r==a[i+1].r) i++;
i++;
}
return 0;
}
problemC:有无数个玩具,第i个玩具价值i元,给定已有的n个玩具的价格和m元。求用着m元最多能卖多少个还没有的玩具。
分析:map判重,for一遍即可。(O(sqrt(m)))
代码:
#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<bitset>
#include<math.h>
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
const int N=100100;
const int MAX=151;
const int mod=100000000;
const int MOD1=1000000007;
const int MOD2=1000000009;
const double EPS=0.00000001;
typedef long long ll;
const ll MOD=998244353;
const ll INF=10000000010;
typedef double db;
typedef unsigned long long ull;
map<int,int>ma;
int b[N];
int main()
{
int i,n,m,x,ans=0;
scanf("%d%d", &n, &m);
for (i=1;i<=n;i++) {
scanf("%d", &x);ma[x]=1;
}
for (i=1;i<=600000;i++)
if (!ma[i]&&m>=i) {
ans++;b[ans]=i;m-=i;
}
printf("%d\n", ans);
for (i=1;i<=ans;i++) printf("%d ", b[i]);
printf("\n");
return 0;
}
problemD:一个人沿着一个湖的边缘顺时针骑自行车,湖的边缘只平行于x轴或y轴。如果这个人原来沿着湖边走然后突然需要左转或者右转如果不转就会掉湖里那么称为危险点。求危险点的个数。
分析:好多人会几何的直接套板子或者算转弯时的叉积。我这种弱鸡选手只能用if判向左转(左转一次ans++)。O(n)
代码:
#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<bitset>
#include<math.h>
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
const int N=1010;
const int MAX=151;
const int mod=100000000;
const int MOD1=1000000007;
const int MOD2=1000000009;
const double EPS=0.00000001;
typedef long long ll;
const ll MOD=998244353;
const ll INF=10000000010;
typedef double db;
typedef unsigned long long ull;
int x[N],y[N],z[N];
int main()
{
int i,n,sum=0,ans=0;
scanf("%d", &n);
for (i=1;i<=n+1;i++) scanf("%d%d", &x[i], &y[i]);
for (i=2;i<=n+1;i++) {
if (x[i-1]==x[i]) {
if (y[i]>y[i-1]) {
if (x[i]<x[i+1]) z[i]=0;
else z[i]=1;
} else {
if (x[i]<x[i+1]) z[i]=1;
else z[i]=0;
}
} else {
if (x[i]>x[i-1]) {
if (y[i]<y[i+1]) z[i]=1;
else z[i]=0;
} else {
if (y[i]<y[i+1]) z[i]=0;
else z[i]=1;
}
}
sum+=z[i];
}
if (sum>0) {
for (i=1;i<=n;i++)
if (z[i]>0) ans++;
} else {
for (i=1;i<=n;i++)
if (z[i]<0) ans++;
}
printf("%d\n", ans);
return 0;
}
problemE:给定一个n个点m条边的无向图。然后要求将每条边有向化,求有向化之后最少有多少个点是入度为0。
分析:很显然能想到如果一个联通块内有环的话,那么每个节点都能入度非0。用并查集合并并判断是否有环即可。O(n)
代码:
#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<bitset>
#include<math.h>
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
const int N=100100;
const int MAX=151;
const int mod=100000000;
const int MOD1=1000000007;
const int MOD2=1000000009;
const double EPS=0.00000001;
typedef long long ll;
const ll MOD=998244353;
const ll INF=10000000010;
typedef double db;
typedef unsigned long long ull;
int f[N],g[N];
int find_f(int x) {
return f[x]==x ? x:f[x]=find_f(f[x]);
}
int main()
{
int i,n,m,x,y,fx,fy,ans=0;
scanf("%d%d", &n, &m);
memset(g,0,sizeof(g));
for (i=1;i<=n;i++) f[i]=i;
while (m--) {
scanf("%d%d", &x, &y);
fx=find_f(x);fy=find_f(y);
if (fx!=fy) { f[fx]=fy;g[fy]=g[fy]|g[fx]; }
else g[fx]=1;
}
for (i=1;i<=n;i++)
if (f[i]==i&&!g[i]) ans++;
printf("%d\n", ans);
return 0;
}
problemF:给定一个n*m的初始矩阵和一个k。要求将这个矩阵变成符合条件的矩阵:(1)剩余的所有点之和为k。(2)整个矩阵的点要么为0要么为x。(3)每个位置的数字只能减不能加。(4)最后的矩阵中所有的x的位置必须是联通的。(5)必须有个位置的x是没有变动的。
分析:按值从大到小用并查集合并即可。如果当前值x整除k并且联通块中点的个数g>=k/x输出答案即可。O(n*mlog(n*m))
代码:
#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<bitset>
#include<math.h>
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
const int N=1010;
const int MAX=151;
const int mod=100000000;
const int MOD1=100000007;
const int MOD2=100000009;
const double EPS=0.00000001;
typedef long long ll;
const ll MOD=1000000009;
const ll INF=10000000010;
typedef double db;
typedef unsigned long long ull;
struct node {
int x,y;
ll z;
node() {}
node(int x,int y,int z):x(x),y(y),z(z) {}
bool operator < (const node &p) const {
return z<p.z;
}
};
priority_queue<node>Q;
int n,m,f[N*N],g[N*N],bo[N][N];
ll tot,a[N][N];
int find_f(int x) {
return f[x]==x ? x:f[x]=find_f(f[x]);
}
void unio(int x,int y) {
int fx=find_f(x),fy=find_f(y);
if (fx==fy) return ;
f[fx]=fy;g[fy]+=g[fx];
}
void dfs(int x,int y,ll z,ll g) {
if (tot>=g) return ;
bo[x][y]=1;bo[x][y]=1;tot++;
if (x>1&&a[x-1][y]>=z&&!bo[x-1][y]) dfs(x-1,y,z,g);
if (x<n&&a[x+1][y]>=z&&!bo[x+1][y]) dfs(x+1,y,z,g);
if (y>1&&a[x][y-1]>=z&&!bo[x][y-1]) dfs(x,y-1,z,g);
if (y<m&&a[x][y+1]>=z&&!bo[x][y+1]) dfs(x,y+1,z,g);
}
void out(int x,int y,ll z,ll g) {
memset(bo,0,sizeof(bo));
tot=0;dfs(x,y,z,g);
for (int i=1;i<=n;i++) {
for (int j=1;j<=m;j++)
if (bo[i][j]) printf("%I64d ", z);
else printf("0 ");
printf("\n");
}
}
int main()
{
int i,j,w,fw;
ll k;
node kk;
scanf("%d%d%I64d", &n, &m, &k);
for (i=1;i<=n;i++)
for (j=1;j<=m;j++) {
scanf("%I64d", &a[i][j]);
Q.push(node(i,j,a[i][j]));
}
for (i=n*m;i;i--) f[i]=i,g[i]=1;
while (!Q.empty()) {
kk=Q.top();Q.pop();
w=(kk.x-1)*m+kk.y;
if (kk.x>1&&a[kk.x-1][kk.y]>=a[kk.x][kk.y]) unio(w,w-m);
if (kk.x<n&&a[kk.x+1][kk.y]>=a[kk.x][kk.y]) unio(w,w+m);
if (kk.y>1&&a[kk.x][kk.y-1]>=a[kk.x][kk.y]) unio(w,w-1);
if (kk.y<m&&a[kk.x][kk.y+1]>=a[kk.x][kk.y]) unio(w,w+1);
fw=find_f(w);
if (k%kk.z==0&&1ll*g[fw]>=k/kk.z) {
printf("YES\n");
out(kk.x,kk.y,kk.z,k/kk.z);
return 0;
}
}
printf("NO\n");
return 0;
}
problemG:给定n个正整数表示n块木块的高度。问有多少切割的方案,要求:切割下的部分在原来的位置上是联通的,每一块木板都是从最顶上算的即不能出现一块木板下面被切但上面却还在的情况。
分析:初一看还以为这题无从下手,我们试试常规的解题方法:当前第i块从上往下数第j个单位向左边联通的切割方案有多少。这样一分我们手动画画会发现每一块木板的dp[i][j]在切割方案上是分为两部分的:顶部一段方案为1的单位点,下面一段方案为x的单位点。记录一下i-1块板的分割位置和x的值就可以推过去算对答案的贡献了。详见代码。O(n)
代码:
#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<bitset>
#include<math.h>
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
const int N=1010;
const int MAX=151;
const int mod=100000000;
const int MOD1=1000000007;
const int MOD2=1000000009;
const double EPS=0.00000001;
typedef long long ll;
const ll MOD=1000000007;
const ll INF=10000000010;
typedef double db;
typedef unsigned long long ull;
int main()
{
int i,n;
ll a,h,la,lh,ld,k,ans=0;
scanf("%d", &n);
la=lh=ld=k=ans=0;
for (i=1;i<=n;i++) {
scanf("%I64d", &a);a--;
ans=(ans+a)%MOD;
if (a>=la) {
k=(lh*ld%MOD+la-lh)%MOD;
ans=(ans+la*k%MOD)%MOD;
lh=la;la=a;ld=k+1;
} else {
if (a>=lh) k=(lh*ld%MOD+a-lh)%MOD;
else k=a*ld%MOD;
ans=(ans+a*k%MOD)%MOD;
lh=a;la=a;ld=k+1;
}
}
printf("%I64d\n", (ans+MOD)%MOD);
return 0;
}