题目地址:https://codeforces.com/contest/1255
题意:
思路:简单贪心策略即可。
代码:
int main()
{
//freopen("input.txt","r",stdin);
int T=read();
while(T--)
{
int a=read(),b=read(),ans=0;
if(a>b) swap(a,b);
ans+=(b-a)/5; a+=ans*5;
ans+=(b-a)/2; a+=(b-a)/2*2;
ans+=(b-a);
printf("%d\n",ans);
}
return 0;
}
题意:
思路:根据题意每个冰箱至少要连接两条边,也就是说每个结点的权值至少要贡献两次,而每个结点只要贡献两次就可以符合题意,所以只要在m==n的情况下输出一个环就可以了。
代码:
const int maxn=1005;
int n,m,a[maxn];
int main()
{
//freopen("input.txt","r",stdin);
int T=read();
while(T--)
{
n=read(),m=read();
REP(i,1,n) a[i]=read();
if(n<=2 || m<n) puts("-1");
else
{
int ans=0;
REP(i,1,n-1) ans+=a[i]+a[i+1];
ans+=a[1]+a[n];
printf("%d\n",ans);
REP(i,1,n-1) printf("%d %d\n",i,i+1);
printf("1 %d\n",n);
}
}
return 0;
}
题意:
思路:通过出现次数可以确定第一个数(二选一),然后因为相邻两个三元组有两个数是一样的,因此可以确定唯一的下一个三元组,也可以确定唯一的下一个数(最终答案应该有两种)
代码:
const int maxn=1e5+5;
int times[maxn],a[maxn][3],n;
set<int> s[maxn];
int main()
{
//freopen("input.txt","r",stdin);
n=read();
REP(i,1,n-2) REP(j,0,2) a[i][j]=read(),times[a[i][j]]++,s[a[i][j]].insert(i);
int k=0,where=0,tempa,tempb;
REP(i,1,n) if(times[i]==1) {k=i; break;}
REP(i,1,n-2)
{
int flag=0;
REP(j,0,2) if(a[i][j]==k) {flag=1; break;}
if(flag) {where=i; break;}
}
printf("%d ",k);
REP(j,0,2) if(times[a[where][j]]==2) tempa=a[where][j];
REP(j,0,2) if(times[a[where][j]]==3) tempb=a[where][j];
printf("%d %d ",tempa,tempb);
REP(i,4,n)
{
#define iter(s) s.begin(),s.end()
vector<int> t(2);
set_intersection(iter(s[tempa]),iter(s[tempb]),t.begin());
where=t[0]==where?t[1]:t[0];
int temp;
REP(j,0,2) if(a[where][j]!=tempa && a[where][j]!=tempb) temp=a[where][j];
printf("%d ",temp);
tempa=tempb; tempb=temp;
}
return 0;
}
题意:一个二维的矩形农场,有一些格子有食物,有k只鸡,给每只鸡分配一个联通的区域,使得食物数目尽可能平分。
思路:将二维数组化为一个连续的一维数组,那么只要分配一段连续的区间,就可以保证在二维联通,然后平均分配即可。
代码:
const int maxn=105;
int a[maxn][maxn],x[maxn*maxn],y[maxn*maxn],b[maxn*maxn];
int r,c,k,n,t[maxn],tot,ans[maxn][maxn];
char s[maxn],g[maxn];
int main()
{
//freopen("input.txt","r",stdin);
REP(i,1,26) g[i]='a'+(i-1);
REP(i,27,52) g[i]='A'+(i-27);
REP(i,53,62) g[i]='0'+(i-53);
int T=read();
while(T--)
{
tot=n=0;
r=read(),c=read(),k=read();
REP(i,1,r)
{
scanf("%s",s+1);
REP(j,1,c) a[i][j]=s[j]=='R',tot+=s[j]=='R';
if(i&1) REP(j,1,c) x[++n]=i,y[n]=j,b[n]=a[i][j];
else REP_(j,c,1) x[++n]=i,y[n]=j,b[n]=a[i][j];
}
int temp=tot/k,cur;
REP(i,1,k) t[i]=temp;
REP(i,1,tot-temp*k) t[i]++;
temp=0,cur=1;
REP(i,1,k)
{
while(temp<t[i])
{
ans[x[cur]][y[cur]]=i;
if(b[cur]) temp++;
cur++;
}
temp=0;
}
while(cur<=n) ans[x[cur]][y[cur]]=k,cur++;
REP(i,1,r)
{
REP(j,1,c) printf("%c",g[ans[i][j]]);
puts("");
}
}
return 0;
}
题意:给定一个长为n(1e6)的数组a,每一次操作可以把 a[i] 传一个给 a[i+1] 或 a[i-1],问最少需要操作多少次,可以使得存在一个k(k>1),数组a中每个元素可以被k整除(0也可以被k整除,初始a[i]<1e6)。
思路:假设数组a的和为sum,那么满足答案的k一定可以整除sum,进一步想,如果满足答案的k是一个非质数,那么既然k已经满足了,k的质因子一定也可以满足,所以选择质数更优。因此思路就是枚举sum的质因子k,计算需要操作多少次,然后更新答案。
对于某个质数k,原本的操作不好计算,我们考虑a的前缀和s,然后发现,把 a[i] 传一个给 a[i+1],相当于只使得 s[i]–,而传给 a[i-1] 只使得 s[i-1]++,也就是说一次操作只会使得s数组中某一个元素(除了最后一个)改变1,再加上数组a每个元素能被k整除与数组s每个元素能被k整除是等价的,于是问题就变为:对于某个质数k,一次操作可以使得s[i] (i 代码: 题意: 思路:以1-2这条线为界,先用方法2询问n-2次,确定其他点在2的左边还是右边,然后用方法1分别询问共n-2次确定两边最远的点,然后再用方法2分别询问共n-4次确定两边那些点是在最远点的左边还是右边,这样根据距离单调性就可以计算出来了:1 -> 变远 -> 最远 -> 变近 -> 2 -> 变远 -> 最远 -> 变近 -> 1 代码:const int maxn=1e6+5;
int n;
LL s[maxn],ans=1ll<<60;
LL solve(LL k)
{
LL ret=0;
REP(i,1,n-1) ret+=min(s[i]%k,k-s[i]%k);
return ret;
}
bool is_prime(LL k)
{
for(LL i=2;i*i<=k;i++)
if(k%i==0) return 0;
return 1;
}
int main()
{
//freopen("input.txt","r",stdin);
n=read();
REP(i,1,n) s[i]=s[i-1]+read();
if(s[n]<2) return puts("-1"),0;
if(is_prime(s[n])) ans=min(ans,solve(s[n]));
else
{
for(LL i=2;i*i<=s[n];i++) if(s[n]%i==0)
{
if(is_prime(i)) ans=min(ans,solve(i));
if(is_prime(s[n]/i)) ans=min(ans,solve(s[n]/i));
}
}
cout<<ans;
return 0;
}
F Point Ordering