1,字串分值和;2,数论,最大不能表示的数;
1,字串分值和;
题意:string s;f(s)表示为s中不同字符的个数,如f(ab)=2,f(aa)=1;
给定一个字符串s,求;字符串长度为1~1e6;
思路:暴力想:需要预处理f[i][j]表示i到j位置的f(i,j)的值,两层for循环,一层i,一层j,相加即可;
但是这样复杂度为O(n^2);会tle;
思考一种O(n)或O(nlogn)的做法;
看这个表格,求和就是把每一行的值相加即可, 但是这是n^2行,所以换一个思路,我们去枚举每一列,把每一列中,每个字母的贡献值相加,最后每一列求和,得到的也是答案;
每个字母的贡献值:( i - pre[ i ] ) * ( n - i + 1);pre储存上次该字母出现的位置(首次为0),i为当前位置;
拿第一个A举例,它在第一位,它对它之后的所有子串都贡献一个1;所以一共贡献
(1-0)*(5-1+1)=5;
第三个A,他在 第三位,它不是第一次出现,所以它对上个A的位置之后的所有位置贡献1个1,一共贡献(3-1)*(5-3+1)=6;
#include<bits/stdc++.h>
#define rep1(i,a,n) for(int i=a;i<n;i++)
#define rep2(i,a,n) for(int i=a;i<=n;i++)
#define per1(i,n,a) for(int i=n;i>a;i--)
#define per2(i,n,a) for(int i=n;i>=a;i--)
#define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false)
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
typedef double db;
const int N=1e6+10;
char s[N];
int last[N],pre[N],nxt[N];
int main()
{
// quick_cin();
cin>>s+1;
int len=strlen(s+1);
rep2(i,0,26)last[i]=0;
rep2(i,1,len)
{
int x=s[i]-'a';
pre[i]=last[x];
last[x]=i;
}
//memset(last,len,sizeof last);
rep2(i,0,26)last[i]=len;
ll ans=0;
rep2(i,1,len)
{
ans+=(i-pre[i])*(len-i+1);
}
cout<<ans;
return 0;
}
2,最大不能表示的数;
对于互质的两个数p,q,px+py 不能表示的最大数为pq-p-q.
证明过程:数论:px+py 不能表示的最大数为pq-p-q的证明 - PIPIBoss - 博客园
#include<bits/stdc++.h>
#define rep1(i,a,n) for(int i=a;i<n;i++)
#define rep2(i,a,n) for(int i=a;i<=n;i++)
#define per1(i,n,a) for(int i=n;i>a;i--)
#define per2(i,n,a) for(int i=n;i>=a;i--)
#define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false)
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
typedef double db;
const int N=1e6+10;
char s[N];
int last[N],pre[N],nxt[N];
int main()
{
quick_cin();
int n,m;
cin>>n>>m;
cout<<n*m-n-m;
return 0;
}
3,蚂蚁感冒
利用蚂蚁走路的特性去解,不要想着啥啊碰头了传染,然后还要掉头啥的;就是把它看成穿过去了就好,只是碰到感染的,它也变成感染的;
所以只要需要找出,在第一个感染蚂蚁左边的往右走的,右边的往左走的蚂蚁总数即可;
但是这是在必须有 左边往右走并且 右边往左走才成立;
假如感染蚂蚁往右走,左边有一个往右走走的,右边全是往右走的,那么最终感染的蚂蚁有几个呢,是1个,因为右边没有往左走的,所以不会碰到感染蚂蚁,也就不会碰到左边往右走的,径统统不成立了,所以必须加个判断条件;
若感染者蚂蚁右走,if(abs(a[i])>flag&&a[i]<0),找出右边往左走的则成立;
若感染者蚂蚁左走,if(abs(a[i])<abs(flag)&&a[i]>0),找出左边往右走的则成立;
#include<bits/stdc++.h>
#define rep1(i,a,n) for(int i=a;i<n;i++)
#define rep2(i,a,n) for(int i=a;i<=n;i++)
#define per1(i,n,a) for(int i=n;i>a;i--)
#define per2(i,n,a) for(int i=n;i>=a;i--)
#define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false)
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
typedef double db;
const int N=1e6+10;
int a[N];
int main()
{
quick_cin();
int n,flag;
int ans=1;
cin>>n;
cin>>flag;
rep2(i,2,n)cin>>a[i];
if(flag>0)
{
rep2(i,2,n)
{
if(abs(a[i])>flag&&a[i]<0)
{
rep2(j,2,n)
{
if(abs(a[j])<flag&&a[j]>0)ans++;
else if(abs(a[j])>flag&&a[j]<0)ans++;
}
cout<<ans;
return 0;
}
}
cout<<1;
return 0;
}
else
{
rep2(i,2,n)
{
if(abs(a[i])<abs(flag)&&a[i]>0)
{
rep2(j,2,n)
{
if(abs(a[j])<abs(flag)&&a[j]>0)ans++;
else if(abs(a[j])>abs(flag)&&a[j]<0)ans++;
}
cout<<ans;
return 0;
}
}
cout<<1;
return 0;
}
cout<<ans;
return 0;
}