题目地址:https://codeforces.com/contest/1372
题意:签到题
思路:
代码:
#define DIN freopen("input.txt","r",stdin);
#define DOUT freopen("output.txt","w",stdout);
#include
#define mem(a,b) memset(a,b,sizeof(a))
#define REP(i,a,b) for(int i=(a);i<=(int)(b);i++)
#define REP_(i,a,b) for(int i=(a);i>=(b);i--)
#define pb push_back
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> P;
int read()
{
int x=0,flag=1;
char c=getchar();
while((c>'9' || c<'0') && c!='-') c=getchar();
if(c=='-') flag=0,c=getchar();
while(c<='9' && c>='0') {x=(x<<3)+(x<<1)+c-'0';c=getchar();}
return flag?x:-x;
}
int main()
{
int T=read();
while(T--)
{
int n=read();
REP_(i,n,1) printf("1 ");
puts("");
}
return 0;
}
题意:给出一个 n,要求两个正整数 a 和 b,使得 a+b=n 并且 LCM(a, b) 尽量小。多组数据。
思路:显然应该找出 n 的大于 1 的最小因子 k,然后把 n 分成 k 份,其中的一份是 a,k-1 份是 b。
代码:
#define DIN freopen("input.txt","r",stdin);
#define DOUT freopen("output.txt","w",stdout);
#include
#define mem(a,b) memset(a,b,sizeof(a))
#define REP(i,a,b) for(int i=(a);i<=(int)(b);i++)
#define REP_(i,a,b) for(int i=(a);i>=(b);i--)
#define pb push_back
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> P;
int read()
{
int x=0,flag=1;
char c=getchar();
while((c>'9' || c<'0') && c!='-') c=getchar();
if(c=='-') flag=0,c=getchar();
while(c<='9' && c>='0') {x=(x<<3)+(x<<1)+c-'0';c=getchar();}
return flag?x:-x;
}
int main()
{
int T=read();
while(T--)
{
int n=read(),x=1;
for(int i=2;i*i<=n;i++)
if(n%i==0) {x=i; break;}
if(x==1) printf("%d %d\n",x,n-x);
else printf("%d %d\n",n/x,1ll*n*(x-1)/x);
}
return 0;
}
题意:有一个操作:选出数组中的一段区间,然后把这段区间中的数全部打乱,使得没有任何数在原来的位置。现在给你一个 n 的排列 a,问你最少操作多少次,可以让 a 变成严格单增数列。
思路:如果本来就单调递增,操作次数为 0 次;然后我们忽略 a 的前后已经排好的(也就是说前面是 1 2 3...
,后面是 n n-1 n-2...
的这些都忽略),剩下的那一段中间的区间中,如果有值等于下标的元素,那么需要 2 次,如果没有那么需要 1 次。
代码:
#define DIN freopen("input.txt","r",stdin);
#define DOUT freopen("output.txt","w",stdout);
#include
#define mem(a,b) memset(a,b,sizeof(a))
#define REP(i,a,b) for(int i=(a);i<=(int)(b);i++)
#define REP_(i,a,b) for(int i=(a);i>=(b);i--)
#define pb push_back
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> P;
int read()
{
int x=0,flag=1;
char c=getchar();
while((c>'9' || c<'0') && c!='-') c=getchar();
if(c=='-') flag=0,c=getchar();
while(c<='9' && c>='0') {x=(x<<3)+(x<<1)+c-'0';c=getchar();}
return flag?x:-x;
}
const int maxn=2e5+5;
int a[maxn],n;
bool check1()
{
REP(i,1,n-1) if(a[i]>a[i+1]) return 0;
return 1;
}
bool check2()
{
int last=n,first=1;
while(last>0 && a[last]==last) last--;
while(first<=n && a[first]==first) first++;
REP(i,first,last) if(a[i]==i) return 0;
return 1;
}
int main()
{
int T=read();
while(T--)
{
n=read();
REP(i,1,n) a[i]=read();
if(check1()) puts("0");
else if(check2()) puts("1");
else puts("2");
}
return 0;
}
题意:有一个奇环,每个结点有一个权值。每次你可以选择一个结点,然后把它的权值替换为与它相邻两个结点权值之和,然后把与它相邻的两个结点删去。问最后剩下一个结点时,权值最大为多少?
思路:一开始想的完全是贪心,然后怎么也不对。
最优的策略一定是选择 (n+1)/2 个不相邻的元素(这里面有一对是相邻的),首先元素不相邻这是肯定的,因为合并的时候只能合并不相邻的两个元素,其次如果你选择的元素个数小于 (n+1)/2 也是有可能的(比如套娃式合并),但是这样显然没有选择 (n+1)/2 个更优。而选择 (n+1)/2 个就意味着,我们要选择所有奇数位,或者所有偶数位,所以做法就是把奇偶分开,然后合并,然后计算前缀和,然后求一段长度为 (n+1)/2 的和的最大值。
代码:
#define DIN freopen("input.txt","r",stdin);
#define DOUT freopen("output.txt","w",stdout);
#include
#define mem(a,b) memset(a,b,sizeof(a))
#define REP(i,a,b) for(int i=(a);i<=(int)(b);i++)
#define REP_(i,a,b) for(int i=(a);i>=(b);i--)
#define pb push_back
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> P;
int read()
{
int x=0,flag=1;
char c=getchar();
while((c>'9' || c<'0') && c!='-') c=getchar();
if(c=='-') flag=0,c=getchar();
while(c<='9' && c>='0') {x=(x<<3)+(x<<1)+c-'0';c=getchar();}
return flag?x:-x;
}
const int maxn=2e5+5;
LL a[maxn],b[maxn];
int main()
{
int n=read(),m=0;
REP(i,1,n) a[i]=read();
for(int i=1;i<=n;i+=2) b[++m]=a[i];
for(int i=2;i<=n;i+=2) b[++m]=a[i];
REP(i,n+1,n*2) b[i]=b[i-n];
REP(i,1,n*2) b[i]+=b[i-1];
LL ans=0;
REP(i,(n+1)/2,n*2) ans=max(ans,b[i]-b[i-(n+1)/2]);
cout<<ans;
return 0;
}
题意:
思路:
代码:
题意:
思路:
代码: