2022 HZNU Programing Contest for Sophomore Grade Group

A. Petr

题意:
给定一个字符串S,问以stat字符串开头,以end字符串结尾的子字符串有多少种,若完全一样视为一种。
题解:
考虑双哈希,以哈希值来判断字符串相等,可以达到 n 2 n^2 n2复杂度。
wa点:对于end字符串,他的开头下表 j j j应该大于等于stat的开头下标 i i i并且 j + l e n 2 − 1 > = i + l e n 1 − 1 j+len2-1>=i+len1-1 j+len21>=i+len11
然后赛时一直T68,因为开了个map,在否循环里判断map里是否已经有这个合法字符串,这样就多了一个log的复杂度,会T。
正确做法应该开个vector,最后再sort,unique去重一下。复杂度为 n 2 + l o g n n^2+logn n2+logn
代码写的太丑了,很难debug。下次应该写一个函数。

#include<bits/stdc++.h> 
typedef long long ll;
const int maxn = 200050;
using namespace std;
ll k1[maxn],k2[maxn];
ll p1=131,p2=13331;
ll mod1=1000000007,mod2=1000000009;
ll hash1[maxn],hash2[maxn];
int main(){
	string s;
	cin>>s;
	string s1,s2;
	cin>>s1>>s2;
	int len1=s1.length(),len2=s2.length();
	k1[0]=k2[0]=1;
	for(int i=1;i<2022;i++)k1[i]=k1[i-1]*p1%mod1,k2[i]=k2[i-1]*p2%mod2;
	for(int i=0;i<s.length();i++){
		hash1[i+1]=(hash1[i]*p1%mod1+s[i]-'a'+1)%mod1;
		hash2[i+1]=(hash2[i]*p2%mod2+s[i]-'a'+1)%mod2;
	}
	ll hh11=0,hh12=0,hh21=0,hh22=0;
	for(int i=0;i<len1;i++){
		hh11=(hh11*p1%mod1+s1[i]-'a'+1)%mod1;
		hh12=(hh12*p2%mod2+s1[i]-'a'+1)%mod2;
	}
	for(int i=0;i<len2;i++){
		hh21=(hh21*p1%mod1+s2[i]-'a'+1)%mod1;
		hh22=(hh22*p2%mod2+s2[i]-'a'+1)%mod2;
	}
	int ans=0;
	vector<pair<ll,ll> >v;
	for(int i=0;i+len1-1<s.length();i++){
		for(int j=max(i,i+len1-len2);j+len2-1<s.length();j++){
			ll hashl1=(hash1[i+len1]-hash1[i]*k1[len1]%mod1+mod1)%mod1;
			ll hashl2=(hash2[i+len1]-hash2[i]*k2[len1]%mod2+mod2)%mod2;
			ll hashr1=(hash1[j+len2]-hash1[j]*k1[len2]%mod1+mod1)%mod1;
			ll hashr2=(hash2[j+len2]-hash2[j]*k2[len2]%mod2+mod2)%mod2;
			ll q1=(hash1[j+len2]-hash1[i]*k1[j+len2-i]%mod1+mod1)%mod1;
			ll q2=(hash2[j+len2]-hash2[i]*k2[j+len2-i]%mod2+mod2)%mod2;
			if(hashl1==hh11&&hashl2==hh12&&hashr1==hh21&&hashr2==hh22)v.push_back(make_pair(q1,q2));
		}
	}
	sort(v.begin(),v.end());
	v.erase(unique(v.begin(),v.end()),v.end());
	cout<<v.size()<<"\n";
	return 0;
}

B. DNA Evolution

题意:
你有一个由A,T,G,C组成的字符串S,有两种操作,一种op=1,将x处的字符修改为C,第二种操作,给你一个长度不超过10的字符串e,e循环出现,(例如:eeeee),问 [ l , r ] [l,r] [l,r]区间内S字符串和(eeee)有几个字符一样。
题解:
考虑维护4种字符以及长度为1-10的全部状态,用多维线段树维护。
tree[id][k][len][m],id表示线段树下标,k表示字符,len表示字符串长度,m表示当前位置取余len后的值。维护每个状态的sum值。
这题线段树开4倍空间会MLE,树状数组会少四倍空间。
树状数组:

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <map>
#include <string>
#include <stack>
#include <cctype>
#include <vector>
#include <queue>
#include <set>
#include <utility>
#include <cassert>
#include <iomanip>
#include <deque>
#include <time.h>
#include <bitset>
using namespace std;
#define ll long long
#define maxn 100005
#define mod 1000000007
#define MOD 998244353
#define Mod 1000000009
#define eps 1e-10
const ll inf=0x3f3f3f3f3f3f3f3f;
const ll INF=0x3f3f3f3f;
const ll mod1=1e9+7;
const ll mod2=1e9+9;
template <typename T>
inline void read(T& X) {X = 0; int w = 0; char ch = 0;while (!isdigit(ch)) { w |= ch == '-'; ch = getchar(); }while (isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();if (w) X = -X;}
char F[200];inline void write(int x){if(x == 0){putchar('0');return;}int tmp = x > 0 ? x : -x;int cnt = 0;if(x < 0)putchar( '-' );while(tmp > 0){F[cnt++] = tmp % 10 + '0';tmp /= 10;}while(cnt > 0)putchar(F[--cnt]) ;}
template<typename T> void print(T x){if(x>9) print(x/10);putchar(x%10+'0');}
ll q_pow(ll x,ll y,ll M){ll ans=1;while(y){if(y%2){y--;ans=ans*x%M;}else {y/=2;x=x*x%M;}}return ans;}
int tree[maxn][4][11][10];
int lowbit(int x){return x&(-x);}
void add(int x,int pos,int k,int val){
	for(;x<maxn;x+=lowbit(x)){
		for(int j=1;j<=10;j++){
			tree[x][k][j][pos%j]+=val;
		}
	}
}
int sum(int i,int xh,int k,int len){
	int ans=0;
	for(;i;ans+=tree[i][k][len][xh],i-=lowbit(i));
	return ans;
}
int query(int l,int r,int xh,int len,int k){
	return sum(r,xh,k,len)-sum(l-1,xh,k,len);
}
map<char,int>mp;
int main() 
{
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	mp['A']=0;mp['T']=1;mp['G']=2;mp['C']=3;
	string s;
	cin>>s;
	for(int i=0;i<s.length();i++){
		add(i+1,i+1,mp[s[i]],1);
	}
	int q;
	cin>>q;
	int op,l,r;
	string ss;
	while(q--){
		cin>>op;
		if(op==1){
			cin>>l>>ss;
			add(l,l,mp[s[l-1]],-1);
			add(l,l,mp[ss[0]],1);
			s[l-1]=ss[0];
		}
		else{
			cin>>l>>r>>ss;
			int len=ss.length();
			int ans=0;
			for(int i=0;i<ss.length();i++){
				ans+=query(l,r,(i+l)%len,len,mp[ss[i]]);
			}
			cout<<ans<<"\n";
		}
		
	}
    return 0;
}

线段树:

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <map>
#include <string>
#include <stack>
#include <cctype>
#include <vector>
#include <queue>
#include <set>
#include <utility>
#include <cassert>
#include <iomanip>
#include <deque>
#include <time.h>
#include <bitset>
using namespace std;
#define ll long long
#define maxn 100005
#define mod 1000000007
#define MOD 998244353
#define Mod 1000000009
#define eps 1e-10
const ll inf=0x3f3f3f3f3f3f3f3f;
const ll INF=0x3f3f3f3f;
const ll mod1=1e9+7;
const ll mod2=1e9+9;
template <typename T>
inline void read(T& X) {X = 0; int w = 0; char ch = 0;while (!isdigit(ch)) { w |= ch == '-'; ch = getchar(); }while (isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();if (w) X = -X;}
char F[200];inline void write(int x){if(x == 0){putchar('0');return;}int tmp = x > 0 ? x : -x;int cnt = 0;if(x < 0)putchar( '-' );while(tmp > 0){F[cnt++] = tmp % 10 + '0';tmp /= 10;}while(cnt > 0)putchar(F[--cnt]) ;}
template<typename T> void print(T x){if(x>9) print(x/10);putchar(x%10+'0');}
ll q_pow(ll x,ll y,ll M){ll ans=1;while(y){if(y%2){y--;ans=ans*x%M;}else {y/=2;x=x*x%M;}}return ans;}
int tree[maxn<<2][4][11][10];
void pushup(int k,int id){
	for(int i=1;i<=10;i++){
		for(int j=0;j<i;j++){
			tree[id][k][i][j]=tree[id<<1][k][i][j]+tree[id<<1|1][k][i][j];
		}
	}
	return ;
}
void update(int id,int l,int r,int k,int pos,int val){
	if(l==r){
		for(int i=1;i<=10;i++){
			tree[id][k][i][pos%i]+=val;
		}
		return ;
	}
	int mid=(l+r)>>1;
	if(mid>=pos)update(id<<1,l,mid,k,pos,val);
	else update(id<<1|1,mid+1,r,k,pos,val);
	pushup(k,id);
}
int query(int id,int l,int r,int k,int xh,int lx,int ly,int len){
	if(l>=lx&&r<=ly)return tree[id][k][len][xh];
	int mid=(l+r)>>1;
	int ans=0;
	if(mid>=lx)ans+=query(id<<1,l,mid,k,xh,lx,ly,len);
	if(mid<ly) ans+=query(id<<1|1,mid+1,r,k,xh,lx,ly,len);
	return ans;
}
map<char,int>mp;
int main() 
{
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	mp['A']=0;mp['T']=1;mp['G']=2;mp['C']=3;
	string s;
	cin>>s;
	for(int i=0;i<s.length();i++){
		update(1,1,s.length(),mp[s[i]],i+1,1);
	}
	int q;
	cin>>q;
	int op,l,r;
	string ss;
	while(q--){
		cin>>op;
		if(op==1){
			cin>>l>>ss;
			update(1,1,s.length(),mp[s[l-1]],l,-1);
			update(1,1,s.length(),mp[ss[0]],l,1);
			s[l-1]=ss[0];
		}
		else{
			cin>>l>>r>>ss;
			int len=ss.length();
			int ans=0;
			for(int i=0;i<ss.length();i++){
//				cout<<query(1,1,s.length(),mp[ss[i]],(i+l)%len,l,r,len)<<"\n";
				ans+=query(1,1,s.length(),mp[ss[i]],(i+l)%len,l,r,len);
			}
			cout<<ans<<"\n";
		}
		
	}
    return 0;
}

D. Find Maximum

题意:
f ( x ) = ∑ i = 0 n − 1 a i b i t ( i ) , b i t ( i ) = ( x > > i ) & 1 f(x)=\sum_{i=0}^{n-1}a_ibit(i),bit(i)=(x>>i)\&1 f(x)=i=0n1aibit(i),bit(i)=(x>>i)&1
x属于 [ 1 , n − 1 ] [1,n-1] [1,n1]
题解:
对n二进制处理,若当前位为1,则可以不取当前位,后面的位置全取,也可以就按照n取。

#include<bits/stdc++.h> 
typedef long long ll;
const int maxn = 200050;
using namespace std;
ll a[maxn];
ll sum[maxn];
int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)cin>>a[i];
	for(int i=1;i<=n;i++)sum[i]=sum[i-1]+a[i];
	string s;
	ll ans=0;
	cin>>s;
	reverse(s.begin(),s.end());
	ll now=0;
//	cout<<s<<"\n";
	for(int i=0;i<n;i++){
//		cout<<sum[n-i]<<" "<<now<<"\n";
		if(s[i]=='1'){
		ans=max(ans,now+sum[n-i-1]);
		now+=a[n-i];
		}
	}
	ans=max(ans,now);
	cout<<ans;
	return 0;
}

E. Bots

题意:
有两个机器人,每个机器人可以走n步,问走完后可能存在多少位置。
题解:
一共可以走 2 n 2n 2n步,答案其实就是 ∑ i = 0 n ∑ j = 0 n C i + j i \sum_{i=0}^n\sum_{j=0}^nC_{i+j}^i i=0nj=0nCi+ji
首先对 ∑ j = 0 n C i + j i \sum_{j=0}^nC_{i+j}^i j=0nCi+ji求解
= C i i + C i + 1 i + . . . + C i + n i =C_i^i+C_{i+1}^i+...+C_{i+n}^i =Cii+Ci+1i+...+Ci+ni
= C i + 1 i + 1 + C i + 1 i + . . . C i + n i =C_{i+1}^{i+1}+C_{i+1}^i+...C_{i+n}^i =Ci+1i+1+Ci+1i+...Ci+ni
由于 C n m = C n − 1 m + C n − 1 m − 1 C_n^m=C_{n-1}^m+C_{n-1}^{m-1} Cnm=Cn1m+Cn1m1
递推得: ∑ j = 0 n C i + j i = C i + n + 1 i + 1 = C i + n + 1 n \sum_{j=0}^nC_{i+j}^i=C_{i+n+1}^{i+1}=C_{i+n+1}^n j=0nCi+ji=Ci+n+1i+1=Ci+n+1n
答案转化为 ∑ i = 0 n C i + n + 1 n \sum_{i=0}^nC_{i+n+1}^n i=0nCi+n+1n
= C n + 1 n + C n + 2 n + . . . + C 2 n + 1 n =C_{n+1}^n+C_{n+2}^n+...+C_{2n+1}^n =Cn+1n+Cn+2n+...+C2n+1n
= C n + 1 n + 1 − 1 + C n + 1 n + C n + 2 n + . . . + C 2 n + 1 n =C_{n+1}^{n+1}-1+C_{n+1}^n+C_{n+2}^n+...+C_{2n+1}^n =Cn+1n+11+Cn+1n+Cn+2n+...+C2n+1n
= C 2 n + 2 n + 1 − 1 =C_{2n+2}^{n+1}-1 =C2n+2n+11

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <map>
#include <string>
#include <stack>
#include <cctype>
#include <vector>
#include <queue>
#include <set>
#include <utility>
#include <cassert>
#include <iomanip>
#include <deque>
#include <time.h>
#include <bitset>
using namespace std;
#define ll long long
#define maxn 3002000
#define mod 1000000007
#define MOD 998244353
#define Mod 1000000009
#define eps 1e-10
const ll inf=0x3f3f3f3f3f3f3f3f;
const ll INF=0x3f3f3f3f;
const ll mod1=1e9+7;
const ll mod2=1e9+9;
template <typename T>
inline void read(T& X) {X = 0; int w = 0; char ch = 0;while (!isdigit(ch)) { w |= ch == '-'; ch = getchar(); }while (isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();if (w) X = -X;}
char F[200];inline void write(int x){if(x == 0){putchar('0');return;}int tmp = x > 0 ? x : -x;int cnt = 0;if(x < 0)putchar( '-' );while(tmp > 0){F[cnt++] = tmp % 10 + '0';tmp /= 10;}while(cnt > 0)putchar(F[--cnt]) ;}
template<typename T> void print(T x){if(x>9) print(x/10);putchar(x%10+'0');}
ll q_pow(ll x,ll y,ll M){ll ans=1;while(y){if(y%2){y--;ans=ans*x%M;}else {y/=2;x=x*x%M;}}return ans;}
ll a[maxn];
ll b[maxn];
ll C(ll n,ll m){
	return a[n]*b[m]%mod*b[n-m]%mod;
}
int main() 
{
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	int n;
	cin>>n;
	a[0]=1;
	for(int i=1;i<=2*n+2;i++)a[i]=a[i-1]*i%mod;
	b[2*n+2]=q_pow(a[2*n+2],mod-2,mod);
	for(int i=2*n+1;i>=0;i--)b[i]=b[i+1]*(i+1ll)%mod;
	cout<<(C(2*n+2,n+1)-1ll+mod)%mod;
    return 0;
}

F. Purification

题意:
你要清除所有的方块,方块"."可以使用法术,清除这一行以及这一列,方块"E"不能使用。输出次数最少的方案或没有。
题解:
方案最少就是n次,选择n个行或者n个列就行了,2b题,输出要按照行列输出,n个列的情况下输出反了一直wa。

#include<bits/stdc++.h> 
typedef long long ll;
const int maxn = 200050;
using namespace std;
vector<int>g[maxn],h[maxn];
int xh[maxn]={0},xl[maxn]={0};
int main(){
	int n;
	char s;
	cin>>n;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			cin>>s;
			if(s=='.'){
			g[i].push_back(j),h[j].push_back(i);
			xh[i]=1;xl[j]=1;
		}
		}
	}
	int sumh=0,suml=0;
	for(int i=1;i<=n;i++){
		if(xh[i])sumh++;
		if(xl[i])suml++;
	}
	if(sumh<n&&suml<n){
		cout<<"-1\n";
		return 0;
	}
	if(sumh==n){
		for(int i=1;i<=n;i++){
			cout<<i<<" "<<g[i][0]<<"\n";
		}
	}
	else{
		for(int i=1;i<=n;i++){
			cout<<h[i][0]<<" "<<i<<"\n";
		}
	}
	return 0;
}

H. Dima and a Bad XOR

题意:
n行,每行m个数,要在n行中每行选一个数,使得XOR不为0.输出任意方案。
题解:
很容易想到二进制拆分,对于每一位,只要能凑够奇数个1就能不为0.有1取1,若为奇数,直接就符合了,若为偶数去找1的能不能选0,就是说选1的行存不存在0,若存在选个0就可以了。

#include<bits/stdc++.h> 
typedef long long ll;
const int maxn = 200050;
using namespace std;
int a[555][555];
int b[555][555];
int ans[555];
int main(){
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			cin>>a[i][j];
		}
	}	
	for(int i=0;i<=10;i++){
		for(int j=1;j<=n;j++){
			for(int k=1;k<=m;k++){
				b[j][k]=(a[j][k]>>i)&1;
			}
		}
		int sum=0;
		int indexi=0,indexj=0;
		for(int j=1;j<=n;j++)ans[j]=0;
		for(int j=1;j<=n;j++){
			int num=0,pos1,pos2;
			for(int k=1;k<=m;k++){
				num+=b[j][k];
				if(b[j][k])ans[j]=k;
				if(b[j][k]==0)pos1=j,pos2=k;
			}
			if(num)sum++;
			if(num>=1&&num<m)indexi=pos1,indexj=pos2;
		}
			if(sum%2){
				cout<<"TAK\n";
				for(int j=1;j<=n;j++){
					if(ans[j]==0)cout<<"1 ";
					else cout<<ans[j]<<" ";	
				}return 0;
			}
			else if(indexi!=0&&indexj!=0){
				cout<<"TAK\n";
				for(int j=1;j<=n;j++){
					if(ans[j]==0)cout<<"1 ";
					else if(j==indexi)cout<<indexj<<" ";
					else cout<<ans[j]<<" ";
				}return 0;
			}
	}
	cout<<"NIE\n";
	return 0;
}

I. RGB Substring (hard version)

题意:
一次可以修改一个字符,问字符串中k个字符符合“RGB”循环的最小修改次数。
题解:
只有3种循环状态,三种都判断一遍就行了。当时2b了,直接上了线段树。

#include<bits/stdc++.h> 
typedef long long ll;
const int maxn = 200050;
using namespace std;
string s;
char mp[3]={'R','G','B'};
struct node{
	int ans[3];
	int len;
}tree[maxn<<2];
void pushup(int id){
	tree[id].len=tree[id<<1].len+tree[id<<1|1].len;
	for(int i=0;i<3;i++){
		tree[id].ans[i]=tree[id<<1].ans[i]+tree[id<<1|1].ans[(i+tree[id<<1].len)%3];
	}
	return;
}
void build(int id,int l,int r){
	if(l==r){
		tree[id].len=1;
		for(int i=0;i<3;i++){
			tree[id].ans[i]=(s[l]!=mp[i]);
		}
		return ;
	}
	int mid=(l+r)>>1;
	build(id<<1,l,mid);
	build(id<<1|1,mid+1,r);
	pushup(id);
}
node query(int id,int l,int r,int lx,int ly){
	if(l>=lx&&r<=ly){
		return tree[id];
	}
	int mid=(l+r)>>1;
	int minn=0x3f3f3f3f;
	node a,b;
	int f1=0,f2=0;
	if(mid>=lx)a=query(id<<1,l,mid,lx,ly),f1=1;
	if(mid<ly)b=query(id<<1|1,mid+1,r,lx,ly),f2=1;
	if(f1&&f2){
		node c;
		c.len=a.len+b.len;
		for(int i=0;i<3;i++){
			c.ans[i]=a.ans[i]+b.ans[(i+a.len)%3];
		}
		return c;
	}
	if(f1)return a;
	if(f2)return b;
}
int main(){
	int t;
	cin>>t;
	while(t--){
		int n,k;
		cin>>n>>k;
		cin>>s;
		s=" "+s;
		build(1,1,n);
		int ans=0x3f3f3f3f;
		for(int i=1;i+k-1<=n;i++){
			node now=query(1,1,n,i,i+k-1);
			for(int j=0;j<3;j++){
				ans=min(ans,now.ans[j]);
			}
		}
		cout<<ans<<"\n";
	}
	return 0;
}

J. Up the Strip

题意:
现在你在n的位置,你有两种操作,一种你可以跳到 n − x , ( x − > [ 1 , n − 1 ] ) n-x,(x->[1,n-1]) nx,(x>[1,n1])的位置。一种你可以跳到 n x , ( x − > [ 2 , n ] ) \frac{n}{x},(x->[2,n]) xn,(x>[2,n]),问跳到1的方案数。
题解:
反向思考,从1跳到n,有两个操作,一个可以跳到 [ i + 1 , n ] 的 位 置 [i+1,n]的位置 [i+1,n]
一个对于所有的 j , [ i ∗ j , i ∗ j + j ) 区 间 都 可 以 由 i 跳 到 j,[i*j,i*j+j)区间都可以由i跳到 j,[ij,ij+j)i
区间数量为 n 2 + n 3 + . . . . \frac{n}{2}+\frac{n}{3}+.... 2n+3n+....是调和级数,时间复杂度为 n l o g n nlogn nlogn
对于区间加法,我们用差分数组可以O(1)维护。
初始值dp[1]=1,由于ans[1]=0,所有dp[2]=-1。

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <map>
#include <string>
#include <stack>
#include <cctype>
#include <vector>
#include <queue>
#include <set>
#include <utility>
#include <cassert>
#include <iomanip>
#include <deque>
#include <time.h>
#include <bitset>
using namespace std;
#define ll long long
#define maxn 5002000
#define mod 1000000007
#define MOD 998244353
#define Mod 1000000009
#define eps 1e-10
const ll inf=0x3f3f3f3f3f3f3f3f;
const ll INF=0x3f3f3f3f;
const ll mod1=1e9+7;
const ll mod2=1e9+9;
template <typename T>
inline void read(T& X) {X = 0; int w = 0; char ch = 0;while (!isdigit(ch)) { w |= ch == '-'; ch = getchar(); }while (isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();if (w) X = -X;}
char F[200];inline void write(int x){if(x == 0){putchar('0');return;}int tmp = x > 0 ? x : -x;int cnt = 0;if(x < 0)putchar( '-' );while(tmp > 0){F[cnt++] = tmp % 10 + '0';tmp /= 10;}while(cnt > 0)putchar(F[--cnt]) ;}
template<typename T> void print(T x){if(x>9) print(x/10);putchar(x%10+'0');}
ll q_pow(ll x,ll y,ll M){ll ans=1;while(y){if(y%2){y--;ans=ans*x%M;}else {y/=2;x=x*x%M;}}return ans;}
ll dp[maxn];
int main() 
{
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	ll n,m;
	cin>>n>>m;
	dp[1]=1;dp[2]=m-1;
	for(int i=1;i<=n;i++){
		dp[i]=(dp[i]+dp[i-1])%m;
		dp[i+1]=(dp[i+1]+dp[i])%m;//j=[i+1,n],dp[j]+=dp[i]
		for(int j=2;j*i<=n;j++){ 
			dp[j*i]=(dp[j*i]+dp[i])%m;
			if(j*i+j<=n)dp[j*i+j]=((dp[j*i+j]-dp[i])%m+m)%m;
		} 
	}
	cout<<dp[n];
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值