前言:终于乐观(optimistic)(打表打漏了,还是比较高)
JZOJ 3382 七夕祭
题目
环(jiang)形(de)均(tai)分(cao)纸(shuai)牌(le)
分析
首先在做这道题之前,要知道均分纸牌,设 ,然后S[i]是A[i]的前缀和,答案就是 ,但是这是环形的,当从k断开可以得到最优解,那么
A | S | |
---|---|---|
K+1 | A[K+1] | S[K+1]-S[K] |
K+2 | A[K+2] | S[K+2]-S[K] |
… | … | … |
N | A[N] | S[N]-S[K] |
1 | A[1] | S[1]+S[N]-S[K] |
2 | A[2] | S[2]+S[N]-S[K] |
… | … | … |
K | A[K] | S[K]+S[N]-S[K] |
因为S[N]=0,所以可以转换成最小的 ,所以就想到了中位数,不需要枚举k,中位数就是k,then时间复杂度O(nlogn+mlogm)
代码
#include <cstdio>
#include <cctype>
#include <algorithm>
using namespace std;
int a[100001],b[100001],n,m,t;
unsigned int ans1,ans2;
int in(){
int ans=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans;
}
int abs(int a){return (a<0)?-a:a;}
int main(){
n=in(); m=in(); t=in();
for (int i=1;i<=t;i++) a[in()]++,b[in()]++;
for (int i=1;i<=n;i++) a[i]+=a[i-1]-t/n;
for (int i=1;i<=m;i++) b[i]+=b[i-1]-t/m;
if (t%n&&t%m) return !printf("impossible");
stable_sort(a+1,a+1+n); stable_sort(b+1,b+1+m);
for (int i=1;i<=n;i++) ans1+=1ll*abs(a[i]-a[(n+1)>>1]);
for (int i=1;i<=m;i++) ans2+=1ll*abs(b[i]-b[(m+1)>>1]);
if (!(t%n)&&!(t%m)) return !printf("both %lld",ans1+ans2);
else if (t%m) return !printf("row %lld",ans1); else return !printf("column %lld",ans2);
}
JZOJ 3383 太鼓达人
题目
长度为M的环形01序列。从不同的位置出发可以得到M个长度为K的01串。M个01串应该是互不相同的。给出K,求出M的最大值,并给出字典序最小的方案。
分析
首先可以发现最后会跳回原来的串,所以就想到了欧拉图,所以深搜。很显然发现答案就是x
当前为x,向
,答案就是x二进制下的第一位,时间复杂度O(
)
代码
#include <cstdio>
using namespace std;
int n,pow; bool ans[2051],v[2051];
bool dfs(int x,int k){
if (v[x]) return 0;
if (k==pow) return 1;
v[x]=1; ans[k]=x&1;
if (dfs((x<<1)&(pow-1),k+1)) return 1;//顺序很重要
if (dfs((x<<1|1)&(pow-1),k+1)) return 1;
return v[x]=0;
}
int main(){
scanf("%d",&n); printf("%d ",pow=1<<n);
for (int i=1;i<n;i++) putchar('0'); dfs(0,1);
for (int i=1;i<=pow-n+1;i++) putchar(ans[i]+48);
return 0;
}
JZOJ 3384 理科男
题目
求在k进制下,a/b小数部分的非循环节长度(即有限小数和混循环小数的前部分)和循环节长度
分析
首先要介绍正向取整法,
所以
所以50分的代码就是用map库或者哈希存下余数,如果余数出现过那么退出,但是非常慢。
2333333333333333333333333333333333333333333333333333333333333333333333333
考虑
所以处理混循环小数和有限小数,保证gcd(a,b)=1,之后
,ans就是第一个问题的答案。
当b=1时证明是有限小数,否则处理过后的混循环小数变成纯循环小数。
思考
,q即所求答案,两边同时除以a得到
根据欧拉定理,
,但
不是最优解,所以在
的最小因数中找到答案。
why?the reason is kind of easy.
反证法,假设
的最小整数解
不是
的因数。
设
因为
所以
根据欧拉定理
,所以
,所以假设不成立。证毕。
时间复杂度
代码
#include <cstdio>
#include <cctype>
#include <algorithm>
using namespace std;
typedef long long ll;
ll a,b,c,t,d;
ll in(){
ll ans=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans;
}
void print(ll ans){if (ans>9) print(ans/10); putchar(ans%10+48);}
ll mul(ll a,ll x){
ll ans=0;
while (x){
if (x&1) ans=(ans+a)%b;
a=(a<<1)%b; x>>=1;
}
return ans;
}
ll ksm(ll a,ll x){
ll ans=1;
while (x){
if (x&1) ans=mul(ans,a);
a=mul(a,a); x>>=1;
}
return ans;
}
ll answer(){
ll n=b,x=b,k=0;
for (int i=2;(ll)i*i<=n;i++)
if (n%i==0){
x=x/i*(i-1);
while (n%i==0) n/=i;
}
if (n>1) x=x/n*(n-1); n=x;
for (int i=2;(ll)i*i<=x;i++)
if (x%i==0){
while (n%i==0&&ksm(c,n/i)==1) n/=i;
while (x%i==0) x/=i;
}
if (x>1&&ksm(c,n/x)==1) n/=x;
return n;
}
int main(){
t=in();
while (t--){
a=in(); b=in(); c=in(); ll ans=0;
a/=(d=__gcd(a,b)); b/=d;
while ((d=__gcd(b,c))>1) ans++,b/=d;
if (ans) print(ans); else putchar('0'); putchar(' '); ans=0;
if (b>1) ans=answer();
if (ans) print(ans); else putchar('0'); putchar('\n');
}
return 0;
}
JZOJ 3385 黑魔法师之门
题目
求
分析
用并查集,当前连的边不需要连就可以连通那么ans=ans*2(初始值为1),否则合并,每次连边后输出ans-1,按秩合并+路径压缩后时间复杂度
代码
#include <cstdio>
#include <cctype>
#define mod 1000000009
using namespace std;
int n,m,ans=1,x,y,f[200001];
int in(){
int ans=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans;
}
int min(int a,int b){return (a<b)?a:b;}
int max(int a,int b){return (a>b)?a:b;}
void print(int ans){if (ans>9) print(ans/10); putchar(ans%10+48);}
int getf(int u){return (f[u]==u)?u:f[u]=getf(f[u]);}
int main(){
n=in(); m=in();
for (int i=1;i<=n;i++) f[i]=i;
while (m--){
x=in(); y=in();
int u=getf(x); int v=getf(y);
if (u==v) ans=(1ll*ans*2)%mod;
else f[min(u,v)]=max(u,v);
if (ans>1) print(ans-1);
else putchar('0'); putchar('\n');
}
return 0;
}
后续
codevs 2485 七夕祭 洛谷 2512 JZOJ 1472 糖果传递 洛谷 1031 均分纸牌 codevs 2486 太鼓达人
codevs 2487 理科男 codevs 1995 黑魔法师之门