比賽鏈接:The Preliminary Contest for ICPC Asia Shanghai 2019
L. Digit sum
簽到題
題目大意:給出n,b,求1-n 的b進制的各個位數之和
思路:因爲n就到10^6可以直接預處理打表。 或者也可以數位DP
代碼:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define ll long long
const int N=1000005;
ll a[12][N];
ll fun(int b,int x)
{
int ans=0;
while(x)
{
ans+=x%b;
x/=b;
}
return (ll)ans;
}
void init()
{
for(int i=2;i<=10;i++)
a[i][1]=1;
for(int i=2;i<=10;i++)
{
for(int j=2;j<=1000000;j++)
a[i][j]=a[i][j-1]+fun(i,j);
}
}
int main()
{
init();
int t,T=1;
scanf("%d",&t);
while(t--)
{
int n,b;
scanf("%d%d",&n,&b);
printf("Case #%d: %lld\n",T++,a[b][n]);
}
return 0;
}
B. Light bulbs
題目大意:有編號爲0~N-1的燈泡,初始都是關閉的,M次操作,每次操作把一個區間 [L,R] 的燈泡改變狀態,問最後打開的燈有多少個。
思路:把區間的左端點,右端點進行排序,差分思想,把左端點權值賦爲1,右端點賦爲-1,前綴和求兩個相鄰端點間的燈泡狀態。 不能直接對n個燈泡差分,T:10^3,N:10^6 ,O(TN)超時
代碼:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
struct node
{
int id,val;
}e[2005];
bool cmp(node a,node b)
{
return a.id<b.id;
}
int main()
{
int t,T=1;
scanf("%d",&t);
while(t--)
{
int n,m;
scanf("%d%d",&n,&m);
int l,r,cnt=0;
for(int i=0;i<m;i++)
{
scanf("%d%d",&l,&r);
l++,r++;
e[cnt].val=1,e[cnt++].id=l;
e[cnt].val=-1,e[cnt++].id=r+1;
}
e[cnt].val=0,e[cnt++].id=n+1;
sort(e,e+cnt,cmp);
int ans=0,res=0;
for(int i=0;i<cnt;)
{
int k=0,x=e[i].id;
while(e[i].id==x)
{
k+=e[i].val;
i++;
}
res+=k;
if(res%2) ans+=e[i].id-x;
}
printf("Case #%d: %d\n",T++,ans);
}
return 0;
}
J. Stone game
題目大意:有n堆石頭,給出每堆石頭的數量,問有多少個集合滿足:
1. 集合內的每一堆石頭數量的和a >= 集合外的所有石頭堆的石頭數量和b
2.集合內去掉任意一個石頭堆後的數量 a-p <=b (去掉任何一個都滿足即去掉最小的滿足,所以p就是集合中石頭數量的最小值)
根據題目即可列出: (x==a-p , y==b)
1. x+p+y= sum (n堆石頭的總數量) 2. x+p>=y
3. x<=y
求得: sum/2-p <= x <= (sum-p)/2
思路:把石頭從大到小排序,dp[ i ] [ j ] 表示第i堆石頭爲最小的時候,集合內的x爲 j 的集合的個數,求 i 爲1~n,j 滿足上面所得公式的集合的總個數
代碼:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define ll long long
const int N=150005;
const ll mod=1000000007;
int a[305];
ll dp[N];
bool cmp(int a,int b)
{
return a>b;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,sum=0;
scanf("%d",&n);
for(int i=1; i<=n; i++)
{
scanf("%d",&a[i]);
sum+=a[i];
}
sort(a+1,a+n+1,cmp);
ll ans=0;
for(int i=1; i<=sum; i++) dp[i]=0;
dp[0]=1;
for(int i=1; i<=n; i++)
{
int l=(sum+1)/2-a[i],r=(sum-a[i])/2;
for(int j=l; j<=r; j++)
ans=(ans+dp[j])%mod;
for(int j=sum-a[i]; j>=0; j--)
dp[j+a[i]]=(dp[j+a[i]]+dp[j])%mod;
}
printf("%lld\n",ans);
}
return 0;
}
F. Rhyme scheme
• 題意:輸出長度爲n的第k個Rhyme scheme
.• Rhyme scheme: 長度爲n的個數是bell number的例子。
• 如果不懂bell number也沒有關係。
• Rhyme scheme就是第i個字母最多是前面出現過的字母+1.
• 比如:AAC是不可以的,ABCAAD是可以的,ABBD也是不可以的
思路:f[ i ] [ j ] 表示長度爲i+1且第一位的字符爲'A'+j 的滿足上面條件的字符串的個數。
代碼:
#include<bits/stdc++.h>
using namespace std;
__int128 f[30][30];
void init()
{
for(int i=0;i<=26;i++) f[0][i]=1;
for(int i=1;i<=26;i++)
for(int j=0;j<=26;j++)
f[i][j]=f[i-1][j]*j+f[i-1][j+1];
}
int main()
{
init();
int t,T=1;
scanf("%d",&t);
while(t--)
{
int n;
__int128 m=0;
char s[30];
scanf("%d%s",&n,s);
int len=strlen(s);
for(int i=0;i<len;i++)
m=m*10+(s[i]-'0');
int c=1;
printf("Case #%d: ",T++);
printf("A");
for(int i=2;i<=n;i++)
{
int k=0;
for(int j=1;j<=c;j++)
{
if(m<=f[n-i][c]) break;
m-=f[n-i][c];
k=j;
}
printf("%c",'A'+k);
c=max(c,k+1);
}
printf("\n");
}
return 0;
}
G. Substring
題意:給了一個母串S, 每次循環給了一個模板串P,問模板串在母串中“匹配”了多少次?“匹配”的意思就是首字母和尾字母一樣,中間字母順序可以換。
思路: 用滑動窗口,對於長度一樣的詢問可以弄在一起搞,因爲窗口大小是一樣的。用map[ i ][ j ] [hash] 記錄長度爲k的且以 i開頭,以j 結尾,哈希值爲hash的子串的個數
代碼:
#include<bits/stdc++.h>
using namespace std;
#define ull unsigned long long
const int N=1e5+7;
const int mod=1e9+7;
char s[N],p[N];
ull ha[30];
map<ull,int>qu[30][30];
map<ull,int>ans[30][30];
struct node
{
int fi,en,siz,id;
ull ha;
}e[N<<1];
void init()
{
ha[0]=N;
for(int i=1;i<26;i++)
ha[i]=(ha[i-1]*N)%mod;
}
bool cmp(node a,node b)
{
return a.siz<b.siz;
}
int len,n,qa[N<<1];
void solve(int x)
{
if(x>len) return;
ull hap=0;
int i=0,j=x-1;
for(int k=i;k<=j;k++) hap=(hap+ha[s[k]-'a'])%mod;
if(qu[s[i]-'a'][s[j]-'a'].count(hap)) ans[s[i]-'a'][s[j]-'a'][hap]++;
while(j<len-1)
{
hap=(hap-ha[s[i]-'a']+mod)%mod;
i++,j++;
hap=(hap+ha[s[j]-'a'])%mod;
if(qu[s[i]-'a'][s[j]-'a'].count(hap)) ans[s[i]-'a'][s[j]-'a'][hap]++;
}
}
int main()
{
init();
int t;
scanf("%d",&t);
while(t--)
{
for(int i=0;i<26;i++)
for(int j=0;j<26;j++)
{
qu[i][j].clear();
ans[i][j].clear();
}
scanf("%s",s);
len=strlen(s);
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%s",p);
int siz=strlen(p);
e[i].siz=siz;
e[i].fi=p[0]-'a';
e[i].en=p[siz-1]-'a';
e[i].id=i;
ull res=0;
for(int j=0;j<siz;j++)
res=(res+ha[p[j]-'a'])%mod;
e[i].ha=res;
qu[e[i].fi][e[i].en][res]=1;
}
sort(e,e+n,cmp);
for(int i=0;i<n;i++)
{
if(e[i].siz!=e[i-1].siz) solve(e[i].siz);
qa[e[i].id]=ans[e[i].fi][e[i].en][e[i].ha];
}
for(int i=0;i<n;i++)
printf("%d\n",qa[i]);
}
return 0;
}