1393C - Pinkie Pie Eats Patty-cakes 二分/公式
最小值要最大一看就很像二分,然后一直wa,最后发现check错了,间隔着放是合理的,但是写到check里会出现问题,比如 4 4 4 4 3 3 2 2 1 1,正确的check应该是如果[i-x,i],k这个数没有出现过,就可以选择k放在这个位置,但是k可能有很多,那么一定是次数最多的是最优的,如果对于一个位置不能放数了,那就不合法;
题解 CF1393C 【Pinkie Pie Eats Patty-cakes】 - huayucaiji 的博客小屋 - 洛谷博客 (luogu.com.cn)
还有一个做法是推公式,感觉推公式才是正解,,,
把出现次数最多的数作为挡板来把别的数间隔掉,比如1 1 1 1 2 2 2 2 3 4 5 6 7 8,出现次数最多的就是1和2,那么就可以变为这种形式,1 2 3 4 1 2 5 6 1 2 7 8 1 2,出现次数最多的次数为x,有num个出现次数最多的数,那么公式就是(n-x*num)/(x-1)+num-1,
n-num*x是剩下的数,除以(x-1)就是每段里面可以放几个数,num-1是作为挡板的数的贡献,比如1可以作为2的贡献;
C. Pinkie Pie Eats Patty-cakes(构造,均分)_issue是fw的博客-CSDN博客
粘一下二分的代码
#include<bits/stdc++.h>
#define int long long
#define lowbit(x) ((x)&(-x))
#define endl '\n'
#define pause system("pause")
using namespace std;
const int N=1e6+5;
const int mod=1e9+7;
const int inf=1e18;
int t,n,a[N],tx[N],fk[N],b[N];
struct node
{
int val,id;
bool operator<(const node&a)const
{
return a.val>val;
}
};
bool check(int x)
{
for(int i=1;i<=n;i++) b[i]=0,tx[i]=fk[i];
priority_queue<node>q;
for(int i=1;i<=n;i++)
{
if(tx[i]) q.push(node{tx[i],i});
}
for(int i=1;i<=n;i++)
{
if(i>x+1)
{
if(tx[b[i-x-1]]) q.push(node{tx[b[i-x-1]],b[i-x-1]});
}
if(q.empty()) return 0;
node u=q.top();q.pop();
tx[u.id]--;
b[i]=u.id;
}
return 1;
}
signed main()
{
//ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin>>t;
while(t--)
{
cin>>n;
for(int i=1;i<=n;i++) tx[i]=fk[i]=0;
for(int i=1;i<=n;i++)
{
cin>>a[i];tx[a[i]]++;fk[a[i]]++;
}
int l=0,r=n-2,ans;
while(l<=r)
{
int mid=l+r>>1;
if(check(mid)) ans=mid,l=mid+1;
else r=mid-1;
}
cout<<ans<<endl;
}
pause;
return 0;
}
济南2021ICPC - D Arithmetic Sequence 三分
假设b数组是最后的等差数列,那么答案就是sum(a[i]-b[i]),a[i]-b[i]=a[i]-(i-1)*d-b[1],然后发现答案其实是和d,b[1]有关的,感性的思考一下可以三分d,然后去求b[1],我们发现b[i]=a[i]-(i-1)*d,我们把所有的b[i]求出来以后,固定一个b[i]作为b[1],那么答案就是a[i]-(i-1)*d-B,也就是b[i]-B,B是被选中的数,那么这个问题也就转化成了货舱选址的问题上,选择b中的中位数来作为b[1]是最优的,这样check函数就写完了
2021ICPC济南区域赛题解CDJKL - 知乎 (zhihu.com)
#include<bits/stdc++.h>
#define int long long
#define ll __int128
#define lowbit(x) ((x)&(-x))
#define endl '\n'
#define pause system("pause")
using namespace std;
const int N=1e6+5;
const int mod=1e9+7;
const int inf=1e18;
ll dabs(ll x){return x<0?-x:x;}
ll n,a[N],b[N];
inline ll read(){
ll x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if(ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
inline void print(ll x){
if(x < 0){
putchar('-');
x = -x;
}
if(x > 9)
print(x / 10);
putchar(x % 10 + '0');
}
ll f(ll d)
{
for(ll i=1;i<=n;i++) b[i]=a[i]-(i-1)*d;
nth_element(b+1,b+(n+1)/2,b+n+1);
//将第(n+1)/2小的数放在第(n+1)/2个位置上
ll mid=b[(n+1)/2],res=0;
for(ll i=1;i<=n;i++) res+=dabs(mid-b[i]);
return res;
}
signed main()
{
//ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
n=read();
for(ll i=1;i<=n;i++) a[i]=read();
ll l=-2e13,r=2e13,ans=0;
while(l<r)
{
ll mid1=l+(r-l)/3;
ll mid2=r-(r-l)/3;
//cout<<mid1<<" "<<mid2<<endl;
if(f(mid1)<f(mid2)) r=mid2-1;
else l=mid1+1;
}
ans=min(f(l),f(r));
print(ans);
pause;
return 0;
}
2021ICPC济南- J Determinant 高斯消元+大数取模
数据范围很大,不能直接高斯消元后去统计负号的个数,需要对大数取模;
定理:对于一个数x和一个奇数p,x%p!=(-x)%p
然后再用高斯消元做就可以了,注意行列式的性质:交换两行,行列式变号,还要注意取模,,
【2021ACM-ICPC亚洲区域赛济南站】C、D、J、K四题超详细题解_keguaiguai的博客-CSDN博客_icpc济南
#include<bits/stdc++.h>
#define int long long
#define ll __int128
#define lowbit(x) ((x)&(-x))
#define endl '\n'
#define pause system("pause")
using namespace std;
const int N=1e6+5;
const int mod=1e9+7;
const int inf=1e18;
int qpow(int a,int b)
{
int res=1;
while(b)
{
if(b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
int getinv(int a){return qpow(a,mod-2);}
int t,n,a[105][105],sum=0;
char s[N];
void gauss()
{
int nl=1,fu=0,res=1;
for(int k=1;k<=n;k++)
{
int p=nl;
for(int i=nl+1;i<=n;i++)
if(a[p][k]<a[i][k]) p=i;
if(a[p][k]==0) continue;
if(p!=nl) res=-res,swap(a[p],a[nl]);
int inv=getinv(a[nl][k]);
res=(res*a[nl][k]%mod+mod)%mod;
for(int i=nl+1;i<=n;i++)
{
int tmp=a[i][k]*inv%mod;
for(int j=k;j<=n;j++)
//a[i][j]=((a[i][j]-tmp*a[nl][j]%mod)%mod+mod)%mod;
a[i][j]=(a[i][j]-tmp*a[nl][j]%mod+mod)%mod;
}
nl++;
}
if(res==sum) cout<<"+\n";
else cout<<"-\n";
}
signed main()
{
// ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin>>t;
while(t--)
{
cin>>n;
cin>>(s+1);sum=0;
for(int i=1;i<=strlen(s+1);i++)
{
int x=s[i]-'0';
sum=(sum*10%mod+x)%mod;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) cin>>a[i][j];
gauss();
}
pause;
return 0;
}
2021济南ICPC - C Optimal Strategy 递推+组合
谁赢谁输一开始就知道,假设最后A拿了X分,B拿了Y分,那么只要是最后两人拿的序列的和是X和Y就可以,考虑对一个数i来说,i出现的次数是tx[i],如果tx[i]为偶数,那么先手一定会先拿走一个把偶数的局面留给后手;如果是偶数,那么两个人拿的数量是一样的;这样其实就可以一对一对的考虑,假设f[i-1]是拿了小于i的方案数,那么对于i这个数来说,如果是偶数,那每对都可以插到任意位置,如果是奇数,那么先手一定先把i拿走,然后局面又和偶数一样了,所以f[i]=f[i-1]*C(sum+x,x)*fac[tx[i]],sum是小于i的总个数,x=tx[i]/2,fac[tx[i]]是阶乘,因为顺序可以不同,因为是按空插进去,一共有sum+x个空,插入x对,所以是C(sum+x,x)
【2021ACM-ICPC亚洲区域赛济南站】C、D、J、K四题超详细题解_keguaiguai的博客-CSDN博客_icpc济南
#include<bits/stdc++.h>
#define int long long
#define ll __int128
#define lowbit(x) ((x)&(-x))
#define endl '\n'
#define pause system("pause")
using namespace std;
const int N=1e6+5;
const int mod=998244353;
const int inf=1e18;
int qpow(int a,int b)
{
int res=1;
while(b)
{
if(b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
int getinv(int a){return qpow(a,mod-2);}
int fac[N],ifac[N],f[N],n,a[N],tx[N];
int C(int a,int b)
{
return (fac[a]*ifac[a-b]%mod)*ifac[b]%mod;
}
void init()
{
fac[0]=1;
for(int i=1;i<=1e6;i++) fac[i]=fac[i-1]*i%mod;
ifac[1000000]=getinv(fac[1000000]);
for(int i=1000000-1;i>=0;i--) ifac[i]=ifac[i+1]*(i+1)%mod;
}
signed main()
{
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
init();
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i],tx[a[i]]++;
int sum=0;f[0]=1;
for(int i=1;i<=n;i++)
{
int x=tx[i]/2;
f[i]=(f[i-1]*C(sum+x,x)%mod)*fac[tx[i]]%mod;
//cout<<"f[i]="<<f[i]<<" sum="<<sum<<" C="<<C(sum+x,x)<<" fac[x]="<<fac[x]<<" t[x]="<<tx[x]<<endl;
sum+=tx[i];
}
cout<<f[n]<<endl;
pause;
return 0;
}
2020CCPC绵阳 博弈搜索
当c0=0&&c1=0或者c0=0&&c1<2&&c2=0时先手输,别的直接进行转移,然后发现一个很重要的事情就是如果牌很多的情况下,无论先手如何选,后手总可以到达c0-2或者c1-3的局面,那么一开始搜的时候直接进行取余即可
2020 CCPC绵阳站G.Game of Cards(博弈搜索)_Azir丶的博客-CSDN博客
#include<bits/stdc++.h>
#define int long long
#define ll __int128
#define lowbit(x) ((x)&(-x))
#define endl '\n'
#define pause system("pause")
using namespace std;
const int N=1e6+5;
const int mod=998244353;
const int inf=1e18;
int qpow(int a,int b)
{
int res=1;
while(b)
{
if(b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
int getinv(int a){return qpow(a,mod-2);}
int t;
bool dfs(int a,int b,int c)
{
if(a==0&&b==0) return 0;
if(a==0&&c==0&&b<2) return 0;
if(a>0&&!dfs(a-1,b,c)) return 1;
if(b>0&&c>0&&!dfs(a,b-1,c-1)) return 1;
if(b>1&&!dfs(a,b-2,c+1)) return 1;
return 0;
}
signed main()
{
//ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin>>t;int ca=0;
while(t--)
{
int a,b,c,d;
cin>>a>>b>>c>>d;
int flag=0;
if(!b&&!c&&!d)
{
if(!a) flag=0;
else if(a&1) flag=0;
else flag=1;
}
else flag=dfs(a%2,b%3,c);
string ans;
if(flag) ans="Rabbit";
else ans="Horse";
cout<<"Case #"<<++ca<<": "<<ans<<endl;
}
pause;
return 0;
}