T1

传送门

解题思路

  发现有一个限制是每个字母都必须相等,那么就可以转化成首尾的差值相等,然后就可以求出\(k-1\)位的差值\(hash\)一下。\(k\)为字符集大小,时间复杂度为\(O(nk)\)。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map> using namespace std;
typedef unsigned long long ull;
typedef long long LL;
const int MAXN = 100005;
const int mod = 131;
const ull base = 666623333;
const int MOD = 1e9+7; int n,cnt,sum[MAXN][60];
char s[MAXN];
LL ans;
ull hsh[MAXN];
map<char,int> mp;
map<ull,int> SUM; int main(){
scanf("%d%s",&n,s+1);
for(int i=1;i<=n;i++){
if(!mp.count(s[i])) mp[s[i]]=++cnt;
sum[i][mp[s[i]]]=1;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=cnt;j++)
sum[i][j]+=sum[i-1][j];
//for(int i=1;i<=n;i++)
//for(int j=1;j<=cnt;j++)
//printf("sum[%d][%d]=%d\n",i,j,sum[i][j]);
for(int i=1;i<=n;i++){
ull now=1;
for(int j=2;j<=cnt;j++)
now=now*base+(ull)(sum[i][j]-sum[i][j-1]+mod);
hsh[i]=now;
SUM[now]=SUM[now]+1;
}
hsh[0]=1;
for(int j=1;j<cnt;j++)
hsh[0]=hsh[0]*base+mod;
SUM[hsh[0]]=SUM[hsh[0]]+1;
for(int i=0;i<=n;i++){
SUM[hsh[i]]=SUM[hsh[i]]-1;
ans=(ans+SUM[hsh[i]])%MOD;
}
printf("%lld\n",ans);
return 0;
}

T2

传送门

解题思路

  二分一个时间,使得一对粒子的距离之和\(<=L\),然后重复\(k\)次,时间复杂度\(O(nklog(MAX)\)。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm> using namespace std;
const int MAXN = 50005;
const double eps = 1e-6; inline int rd(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)) f=ch=='-'?0:1,ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
return f?x:-x;
} void out(int x){
if(!x) return ;out(x/10);putchar('0'+x%10);
} int n,L,k,Maxx[3],Maxy[3],ans[105][2];
bool visx[MAXN],visy[MAXN];
double disx[3],disy[3],now;
struct Data{
int v,t;
}a[MAXN],b[MAXN]; inline bool check(int tmp,double lim){
Maxx[1]=Maxx[2]=Maxy[1]=Maxy[2]=disx[1]=disx[2]=disy[1]=disy[2]=0;
for(register int i=1;i<=n;i++){
if(!visx[i] && a[i].t<=lim) {
if((double)(lim-a[i].t)*a[i].v>disx[1]) {
Maxx[2]=Maxx[1];disx[2]=disx[1];
disx[1]=(double)(lim-a[i].t)*a[i].v;Maxx[1]=i;
}
else if((double)(lim-a[i].t)*a[i].v>disx[2]) Maxx[2]=i,disx[2]=(double)(lim-a[i].t)*a[i].v;
}
if(!visy[i] && b[i].t<=lim){
if((double)(lim-b[i].t)*b[i].v>disy[1]){
Maxy[2]=Maxy[1];disy[2]=disy[1];
disy[1]=(double)(lim-b[i].t)*b[i].v;Maxy[1]=i;
}
else if(((double)(lim-b[i].t)*b[i].v>disy[2])) Maxy[2]=i,disy[2]=(double)(lim-b[i].t)*b[i].v;
}
if(disx[2]+disy[2]>=L) return 0;
}
if(!Maxx[1] || !Maxy[1]) return 1;
if(disx[1]+disy[1]<L) return 1;
if(disx[2]+disy[2]>=L) return 0;
ans[tmp][0]=Maxx[1];ans[tmp][1]=Maxy[1];now=lim;
return 0;
} int main(){
n=rd(),L=rd(),k=rd();double l,r,mid;
for(register int i=1;i<=n;i++)
a[i].t=rd(),a[i].v=rd();
for(register int i=1;i<=n;i++)
b[i].t=rd(),b[i].v=rd();
for(register int i=1;i<=k;i++){
l=now;r=1e9+2e8;
while(r-l>=eps){
mid=(l+r)/2;
if(check(i,mid)) l=mid+eps;
else r=mid-eps;
}
visx[ans[i][0]]=1;visy[ans[i][1]]=1;
out(ans[i][0]),putchar(' '),out(ans[i][1]),putchar('\n');
}
return 0;
}

T3

传送门

解题思路

  状压\(dp\),考场上脑抽了写了个\(2^{3^{质因数}}\)级别的垃圾做法。。正解十分玄学,前\(6\)位三进制状压表示每个质因数出现的次数,后\(21\)为二进制状压表示哪两个质因数不能同时出现,然后用\(map\)来存状态。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<map>
#define int long long using namespace std;
typedef long long LL;
const int MOD = 1e9+7;
const int poww[8] = {1,3,9,27,81,243,729,2187}; LL n;
int ans,a[55],cnt,num[55],ban[55];
map<int,int> mp;
map<int,int>::iterator it; inline void init(){
int x=n;
for(LL i=2;i*i<=x;i++){
if(x%i) continue;
a[cnt]=i;
while(!(x%i)) x/=i,num[cnt]++;
cnt++;
}
if(x!=1) a[cnt]=x,num[cnt++]=1;
} int get_new(int S,int now){
int ret=S,bit=1;
for(int i=0;i<cnt;i++){
if((now&(1<<i)) && S/bit%3<2) ret+=bit;
bit*=3;
}
for(int i=0;i<cnt;i++)
for(int j=i+1;j<cnt;j++){
if((now&(1<<i)) && ((S/poww[j])%3>0) && (!((S/bit)&1))) ret+=bit;
else if((now&(1<<j)) && ((S/poww[i])%3>0) && (!((S/bit)&1))) ret+=bit;
bit<<=1;
}
return ret;
} inline int get_num(int S){
int ret=1;
for(int i=0;i<cnt;i++)
if(S&(1<<i)) ret*=num[i],ret%=MOD;
return ret;
} signed main(){
scanf("%lld",&n);int kk=0;
init();it=mp.insert(make_pair(0,1)).first;
while(it!=mp.end()){kk++;
ans+=it->second;ans%=MOD;
int tmp=it->first,now=0,tot=0,flag,k;
for(int i=0;i<cnt;i++){
if(tmp%3<2) now|=(1<<i);
tmp/=3;
}
for(int i=0;i<cnt;i++)
for(int j=i+1;j<cnt;j++){
if(tmp&1) ban[++tot]=(1<<i)|(1<<j);
tmp>>=1;
}
for(int i=now;i;i=(i-1)&now){
flag=false;
for(int j=1;j<=tot;j++)
if((ban[j]|i)==i) {flag=true;break;}
if(flag) continue;
k=get_new(it->first,i);
if(mp.find(k)==mp.end()) mp.insert(make_pair(k,0));
mp[k]+=it->second*get_num(i)%MOD;mp[k]%=MOD;
}
it++;
}
printf("%lld\n",(ans-1+MOD)%MOD);
return 0;
}

最新文章

  1. KAOS模型
  2. UITableViewController和XML解析还有地图的简单结合
  3. redis使用简介
  4. AFNnetworking详解
  5. Caused by: javax.xml.bind.JAXBException: standardPremiumUpdateMessageDTO is not a valid property on
  6. Sharded实现学习-我们到底能走多远系列(32)
  7. ntoskrnl.exe损坏或丢失的解决方式
  8. Django Model数据访问Making queries
  9. WP8手机解锁时提示“请确保IPOVERUSBSVC服务正常运行”解决方法
  10. Linux下报 java.net.SocketException权限不够 异常解决
  11. Linux上ld和ld.so命令的区别
  12. android退出Activity
  13. uvalive 6888 Ricochet Robots bfs
  14. C语言之形参和实参
  15. 【Nginx系列】Nginx虚拟主机的配置核日志管理
  16. gitlab钩子搭建
  17. 初次部署django+gunicorn+nginx
  18. MyBatis 集合操作语法范例:配合SQL的in关键字
  19. [BZOJ3451][Tyvj1953]Normal(点分治+FFT)
  20. FZU 2273 Triangles 第八届福建省赛 (三角形面积交 有重边算相交)

热门文章

  1. 洛谷P1122 最大子树和 (树状dp)
  2. 兼容新旧浏览器的flex写法
  3. MySql 5.7.26(MySQL8)安装教程
  4. Some Simple Mistakes I had
  5. 升级到Xcode 5.1和iOS 7遇到的各种问题及解决办法汇总:
  6. Regex 正则零宽断言
  7. PHP面试 MySQL的SQL语句编写
  8. 从上一个页面跳入新页面时,如何拿URL中的参数
  9. jmeter 5 参数化
  10. 关系型数据的分布式处理系统:Cobar