题目链接:https://codeforces.com/contest/1370
最后的F题卡了半天,不过最后还是找到了问题。补了3.5题~
设 g c d ( a , b ) = k , a = x k , b = y k , x 与 y 互 质 设gcd(a,b)=k ,a=xk,b=yk,x与y互质 设gcd(a,b)=k,a=xk,b=yk,x与y互质,想让k更大的话,x和y要尽量小,x=1,y=2正好是最小的。所以不难发现k=n/2
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define FOR(i,l,r) for(int i=l;i<=r;i++)
#define ROF(i,l,r) for(int i=l;i>=r;i--)
#define pb(x) push_back(x)
#define mp(x,y) make_pair(x,y)
#define r(x) read(x)
#define rr(x,y) read(x);read(y)
#define rrr(x,y,z) read(x);read(y);read(z)
#define sss(str) scanf("%s",str+1)
#define ssf(x) scanf("%lf",&x)
#define aLL(x) x.begin(),x.end()
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef pair<int,int> pt;
const int N=2e5+5;
const int M=2e3+5;
const int INF=2e9;
const int sz=15;
const int mod=1e9+7;
const double eps = 1e-8;
const double pi= acos(-1);
template<class T>
inline void read(T &x)
{
char c;x=1;
while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
T res=c-'0';
while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
x*=res;
}
int n,m;
char str[N];
int f[N];
int main()
{
int t;
r(t);
while(t--){
r(n);
cout<<n/2<<endl;
}
return 0;
}
假设有x个奇数,y个偶数。
根据小学的姿势,奇数+奇数=偶数,偶数+偶数=偶数。
这里一共有偶数个数,我们只需要让奇数和奇数匹配,偶数和偶数匹配【匹配不了的丢掉,多出来的丢一对】就好了
int n,m;
char str[N];
int f[N];
int main()
{
int t;
r(t);
while(t--){
r(n);
vector<int> v1,v2;
FOR(i,1,n*2){
int a;
r(a);
if(a&1) v1.pb(i);
else v2.pb(i);
}
int a=0,b=0,c=v1.size(),d=v2.size();
if(v1.size()%2==0){
if(v1.size()) a=2;
else b=2;
}
else{
c--;
d--;
}
for(int i=a;i<c;i+=2){
cout<<v1[i]<<' '<<v1[i+1]<<endl;
}
for(int i=b;i<d;i+=2){
cout<<v2[i]<<' '<<v2[i+1]<<endl;
}
}
return 0;
}
找规律。
①:n=1,此时先手必输
②:n为奇数,此时先手必胜
③:n=2,先手必胜
④:把n质数分解,若含2个及以上的2,和其他质数,那必胜
⑤:只有一个2,如果其他质数多于1个,必胜,否则必输
⑥:必输
int n,m;
char str[N];
int f[N];
int main()
{
int t;
r(t);
while(t--){
r(n);
int a=0;
if(n&1){
if(n==1) cout<<"FastestFinger\n";
else cout<<"Ashishgup\n";
continue;
}
if(n==2){
cout<<"Ashishgup\n";
continue;
}
while(n%2==0){
a++;
n>>=1;
}
if(n>1&&a>=2){
cout<<"Ashishgup\n";
}
else if(n>1&&a>=1){
bool flag=1;
FOR(i,2,sqrt(n)){
if(n%i==0){
flag=0;
break;
}
}
if(!flag) cout<<"Ashishgup\n";
else cout<<"FastestFinger\n";
}
else{
cout<<"FastestFinger\n";
}
}
return 0;
}
答案肯定是数组中的一个,二分答案,如果他可以携带的序列不少于k个,那肯定可以,再找更小的
【假如说答案在奇数/偶数段】偶数/奇数段随便都可以选,奇数/偶数段的数必须不大于这个答案
int n,m;
char str[N];
int f[N],g[N];
bool check(int x,bool tmp)
{
int ans=0;
FOR(i,1,n){
if(tmp){
ans++;
tmp^=1;
}
else{
if(f[i]<=g[x]){
ans++;
tmp^=1;
}
}
}
return ans>=m;
}
int main()
{
rr(n,m);
FOR(i,1,n){
r(f[i]);
g[i]=f[i];
}
sort(g+1,g+n+1);
int l=1,r=n;
int ans=0;
while(l<=r){
int mid=l+r>>1;
if(check(mid,1)||check(mid,0)){
ans=mid;
r=mid-1;
}
else l=mid+1;
}
cout<<g[ans]<<endl;
return 0;
}
这题一直不知道怎么处理,原来要把串相同的地方去掉,之后就好做了。
剩下的就是0000110100101之类的串,我们每次操作都选择01010101来消除,这样消除的就是最大的。
int n,m;
char str1[N],str2[N];
int f[N];
int main()
{
r(n);
sss(str1);
sss(str2);
int a=0,b=0;
FOR(i,1,n){
if(str1[i]=='1') a++;
if(str2[i]=='1') b++;
}
if(a!=b){
cout<<-1<<endl;
return 0;
}
vector<char> v;
FOR(i,1,n){
if(str1[i]!=str2[i]){
v.pb(str1[i]);
}
}
a=b=0;
for(char x:v){
if(x=='1'){
a++;
if(b) b--;
}
else{
b++;
if(a) a--;
}
}
cout<<a+b<<endl;
return 0;
}
交互题,一开始就有思路。
首先找所有的点,输出一定是 这条路径中的一个点 和 这条路径的长度
然后我们以已知的这个点为根dfs,记录每层有什么点。
假设路径长度为k,答案之一距离根的max肯定大于等于(k+1)/2,我们就先找这个远的点。
下界为(k+1)/2,上界为k,二分查找即可。
得到这个点之后,再以这个点为根,那么距离这个点k距离的点集中再查询一次,即可得到另一个点
int n,m;
char str[N];
int f[M];
vector<int> v[M],lvl[M],tmp;
pt query(vector<int> &tt)
{
if(!tt.size()) return mp(-1,-1);
cout<<"? "<<tt.size();
for(int x:tt) cout<<" "<<x;
cout<<endl;
int a,b;
cin>>a>>b;
return mp(a,b);
}
void dfs(int x,int fa,int dep)
{
m=max(m,dep);
lvl[dep].pb(x);
for(int y:v[x]){
if(y!=fa){
dfs(y,x,dep+1);
}
}
}
int main()
{
int t;r(t);
while(t--){
r(n);
m=0;
tmp.clear();
lvl[0].clear();
FOR(i,1,n){
v[i].clear();
lvl[i].clear();
tmp.pb(i);
}
FOR(i,1,n-1){
int a,b;rr(a,b);
v[a].pb(b);
v[b].pb(a);
}
pt res=query(tmp);
int root=res.fi,dep=res.se;
dfs(root,0,0);
int l=(dep+1)/2,r=min(m,dep),ans1;
while(l<=r){
int mid=l+r>>1;
res=query(lvl[mid]);
if(res.se==dep){
ans1=res.fi;
l=mid+1;
}
else r=mid-1;
}
FOR(i,0,n) lvl[i].clear();
dfs(ans1,0,0);
res=query(lvl[dep]);
cout<<"! "<<ans1<<' '<<res.fi<<endl;
string s;
cin>>s;
}
return 0;
}