今天的题目水到连出题人都懒得讲了。
T1 题目简述:jzoj5456
解题思路:大水题。
贪心。由于题目要求字典序最小,因此要保证身高越低的排名越靠前。
先把人按身高从高到低排序,然后依次插入vector。
这样可以保证在身高为a[i]的人插入vector前vector内的人身高都大于a[i]。
由于要保证当前这个人排名最靠前,因此可以对(他的要求)和(比他身高高的人数-他的要求)取min,
再插入vector的第(min+1)个位置即可。
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #include<vector> #include<utility> using namespace std; int n; struct uio{ int hei,ask; }peo[100001]; vector<int> vec; bool cmp(uio x,uio y) { return x.hei>y.hei; } int main() { freopen("queue.in","r",stdin); freopen("queue.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d%d",&peo[i].hei,&peo[i].ask); sort(peo+1,peo+1+n,cmp); for(int i=1;i<=n;i++) { int tmp=min(peo[i].ask,i-1-peo[i].ask); if(tmp<0) {printf("impossible\n");return 0;} vec.insert(vec.begin()+tmp,peo[i].hei); } for(int i=0;i<vec.size();i++) printf("%d ",vec[i]); return 0; }
T2 题意简述:jzoj5458
解题思路:大水题。
线性筛的同时顺便记录满足要求的数的个数,再顺便求一下前缀和就行了。
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #define ll long long using namespace std; ll n,cnt,pri[10000001],num[10000001],jdg[10000001]; void getnum() { for(ll i=2;i<=10000000;i++) { if(jdg[i]==0) pri[++cnt]=i,num[i]=1; num[i]+=num[i-1]; for(ll j=1;j<=cnt;j++) { if(pri[j]*i>10000000) break; if(!jdg[i]) num[pri[j]*i]=1; jdg[i*pri[j]]=1; if(!(i%pri[j])) break; } } } int main() { freopen("prime.in","r",stdin); freopen("prime.out","w",stdout); getnum(); scanf("%lld",&n); for(ll i=1;i<=n;i++) { ll u,v; scanf("%lld%lld",&u,&v); printf("%lld\n",num[v]-num[u-1]); } return 0; }
T3 题意简述:jzoj5462
解题思路:大水题+无F♂A可说的题。
正解写了一大堆奇奇怪怪的东西,其实根本没有那么麻烦。
解法一:Hash,也就是本代码描述的算法。
解法二:Trie树。
解法三:后缀自动机。 <-- ErkkiErkko大佬强力推荐
至于为什么说无F♂A可说是因为题解中对于解法一给了一个式子,大概意思就是:
模数取10^9时,只有0.67%的概率正确。
模数取10^10时,有60.65%的概率正确。
模数取10^12时,有99.61%的概率正确。
您取一个10^15~10^16大小的模数就能保证正确了。
我:???(顺带一提,我的模数是10^8级别的)
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #define MOD 383109303154469 #define base 233 #define ll long long using namespace std; ll n,m,ans=1,num[200001],bpow; char a[200001]; int main() { freopen("article.in","r",stdin); freopen("article.out","w",stdout); scanf("%lld%lld",&n,&m); scanf("%s",a+1); bpow=1; for(ll i=1;i<m;i++) bpow=bpow*base%MOD; for(ll i=1;i<=m;i++) num[1]=(num[1]*base+a[i])%MOD; for(ll i=m+1;i<=n;i++) num[i-m+1]=((num[i-m]-bpow*a[i-m]%MOD+MOD)*base+a[i])%MOD; // for(int i=1;i<=n-m+1;i++) // for(int j=i;j<=i+m-1;j++) // num[i]=(num[i]*base+a[j])%MOD; sort(num+1,num+1+n-m+1); // for(ll i=1;i<=n-m+1;i++) printf("%lld\n",num[i]); for(ll i=2;i<=n-m+1;i++) if(num[i]!=num[i-1]) ans++; printf("%lld\n",ans); return 0; }