A - tokitsukaze and Counting
求
[
L
,
R
]
[L,R]
[L,R]之间有多少个数能被
x
x
x整除.
考虑前缀
[
1
,
L
]
[1,L]
[1,L],一共有
L
/
x
L/x
L/x个数字是
x
x
x的倍数.签到题不多讲…
#include <cstdio>
int main(){
int T;
scanf("%d",&T);
while(T--){
long long L,R,x;
scanf("%lld%lld%lld",&L,&R,&x);
printf("%lld\n",(R/x)-((L-1)/x));
}
}
B - tokitsukaze and RPG
求
x
x
x能被最多的
a
[
i
]
a[i]
a[i]整除,且这样的
x
x
x有多少个.
将
a
[
i
]
a[i]
a[i]合并,然后对每一个
i
i
i进行操作,这样合并之后的复杂度是
O
(
n
l
g
n
)
O(nlgn)
O(nlgn)的.
#include <cstdio>
int cnt[1000005];
int res[1000005];
int main(){
int n,k,a,mx=0;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++){
scanf("%d",&a);
cnt[a]++;
if(mx<a)mx=a;
}
for(int i=1;i<=mx;i++){
if(cnt[i]){
for(int j=i;j<=k;j+=i)res[j]+=cnt[i];
}
}
int resT=0,t=0;
for(int i=1;i<=k;i++){
if(resT<res[i])resT=res[i],t=0;
if(resT==res[i])t++;
}
printf("%d %d\n",resT,t);
}
C - tokitsukaze and Number Game
问将数
X
X
X重排序以后最大的数,且这个数能被8整除.
根据
8
8
8的性质,任意被8整除的数字的末尾数字
000
∼
999
000\sim 999
000∼999构成循环节,从而对最后三位暴力算即可.
如果数字不满3位,我就干脆直接特判,节省脑子…
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
bool cmp(char x,char y){
return x>y;
}
int cnt[11],cmc[11];
string s,nu[10][105],ss,sj;
int main(){
ios::sync_with_stdio(0);
int T;
ss="0";
for(int i=0;i<10;i++){
ss[0]=i+'0';nu[i][0]="";
for(int j=1;j<=100;j++)nu[i][j]=nu[i][j-1]+ss;
}
cin>>T;
while(T--){
cin>>s;
int slen=s.length();
if(slen<3){
if(slen==1){
if((s[0]-'0')%8==0){
cout<<s<<endl;
}else cout<<"-1"<<endl;
}else{
int g=(s[1]-'0')*10+s[0]-'0',t=(s[0]-'0')*10+s[1]-'0',res=-1;
if(g%8==0){
if(res<g)res=g;
}
if(t%8==0){
if(res<t)res=t;
}
cout<<res<<endl;
}
continue;
}
memset(cnt,0,sizeof(cnt));
for(int i=0;i<slen;i++){
cnt[s[i]-'0']++;
}
string res;bool resed=0;
sj="000";
for(int i=0;i<1000;i+=8){
memset(cmc,0,sizeof(cmc));
ss="";
int g=i;
for(int j=0;j<3;j++){
cmc[g%10]++;
sj[2-j]=g%10+'0';
g/=10;
}
bool f=1;
for(int j=0;j<10;j++){
if(cmc[j]>cnt[j]){f=0;break;}
}
if(!f)continue;
for(int j=9;j>=0;j--){
ss+=nu[j][cnt[j]-cmc[j]];
}
ss+=sj;
//cout<<"yese"<<ss<<endl;
if(resed){
if(res<ss)res=ss;
}else res=ss,resed=1;
}
if(resed)cout<<res<<endl;else cout<<"-1"<<endl;
}
//system("pause");
}
D - tokitsukaze and Inverse Number
循环移位区间
[
L
,
R
]
k
[L,R]k
[L,R]k次,一共执行
Q
Q
Q次,每次询问得到的序列的逆序数的奇偶性.
考虑
[
L
,
R
]
[L,R]
[L,R]移动一次,那么假设
[
L
,
R
]
[L,R]
[L,R]之间有
x
x
x个数比第一个数大,有
a
−
1
−
x
a-1-x
a−1−x个数比第一个数小,那么显然答案是
o
l
d
r
e
s
+
a
−
1
−
x
−
x
≡
o
l
d
r
e
s
+
a
−
1
(
m
o
d
2
)
oldres+a-1-x-x\equiv oldres+a-1 \pmod 2
oldres+a−1−x−x≡oldres+a−1(mod2).所以无论区间内的数字是什么,其结果只与操作数的区间长度有关.
#include <cstdio>
#include <iostream>
using namespace std;
int bit[100005];
int a[100005],n;
#define lowbit(_x) ((_x)&-(_x))
void add(int x){
while(x<=n){
bit[x]++;
x+=lowbit(x);
}
}
int sum(int x){
int res=0;
while(x>0){
res+=bit[x];
x-=lowbit(x);
}
return res;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
int res;
for(int i=n;i>=1;i--){
res+=sum(a[i]);
add(a[i]);
res&=1;
}
//printf("before %d\n",res);
int q,l,r,k;
scanf("%d",&q);
while(q--){
scanf("%d%d%d",&l,&r,&k);
printf("%d\n",res^=(k&1)&((r-l)&1));
}
//system("pause");
}
E - tokitsukaze and Similar String
求串
s
[
l
1
.
.
.
r
1
]
s[l_1...r_1]
s[l1...r1]和
s
[
l
2
.
.
.
r
2
]
s[l_2...r_2]
s[l2...r2]之间的相似度.相似度如题定义.
暴力算
s
s
s整体移位
0
∼
25
0\sim 25
0∼25次的所有hash值,暴力判断即可…
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
char s[100005];
unsigned long long HA[26][100005],HB[100005];
unsigned long long gethash(unsigned long long *Hash,int x, int len)
{
return Hash[x + len - 1] - Hash[x - 1] * HB[len];
}
int main(){
int n,q,slen;
scanf("%d%s%d",&n,s+1,&q);
int x,y,l;
slen=strlen(s+1);
HB[0]=1;
for(int i=1;i<=slen;i++){
for(int j=0;j<26;j++)HA[j][i]=HA[j][i-1]*233+(s[i]-'a'+j)%26+'a';
HB[i]=HB[i-1]*233;
}
while(q--){
scanf("%d%d%d",&x,&y,&l);
unsigned long long hx,hy=gethash(HA[0],y,l);
int res=-1;
for(int j=0;j<26;j++){
hx=gethash(HA[j],x,l);
if(hx==hy){
res=j;
break;
}
}
printf("%d\n",min(res,26-res));
}
//system("pause");
}
F - tokitsukaze and Unlimited Array
求多项式函数构造的数列
a
[
i
]
=
f
(
i
)
a[i]=f(i)
a[i]=f(i)的
N
N
N阶差分的级数和.
首先由
N
N
N阶差分的性质所有次数小于
n
n
n的
f
f
f项都会被差分为0.
从而在答案的贡献上
f
(
x
)
≡
g
(
x
)
=
a
n
x
n
f(x)\equiv g(x)=a_nx^n
f(x)≡g(x)=anxn.
由差分的性质,答案等于:
r
e
s
=
a
n
n
!
res=a_n n!
res=ann!
所以答案即是求
a
n
n
!
a_n n!
ann!,由于
n
n
n很大,分段打表即可…
#include <iostream>
#include <cstdio>
using namespace std;
const long long mod=1e9+7;
const long long p=1000000007;
const long long N=10000000;
const long long num[]={1,682498929,491101308,76479948,723816384,
67347853,27368307,625544428,199888908,888050723,
927880474,281863274,661224977,623534362,970055531,
261384175,195888993,66404266,547665832,109838563,
933245637,724691727,368925948,268838846,136026497,
112390913,135498044,217544623,419363534,500780548,
668123525,128487469,30977140,522049725,309058615,
386027524,189239124,148528617,940567523,917084264,
429277690,996164327,358655417,568392357,780072518,
462639908,275105629,909210595,99199382,703397904,
733333339,97830135,608823837,256141983,141827977,
696628828,637939935,811575797,848924691,131772368,
724464507,272814771,326159309,456152084,903466878,
92255682,769795511,373745190,606241871,825871994,
957939114,435887178,852304035,663307737,375297772,
217598709,624148346,671734977,624500515,748510389,
203191898,423951674,629786193,672850561,814362881,
823845496,116667533,256473217,627655552,245795606,
586445753,172114298,193781724,778983779,83868974,
315103615,965785236,492741665,377329025,847549272,698611116
};
long long getnum(long long n){
if(!n)return 1;
long long tmp=num[n/N];
for(int i=n/N*N+1;i<=n;i++)tmp=(long long)tmp*i%p;
return tmp;
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
long long x,y;
for(int i=1;i<=m;i++){
scanf("%lld%lld",&x,&y);
if(y==n)break;
}
printf("%lld\n",x*getnum(n)%mod);
//system("pause");
}